* remove own list functionality from hash
* use hlist_head, hlist_node in hash
- * don't use callbacks for compare+choose in hash
+ * don't use callbacks for choose in hash
* think about more efficient ways instead of abstraction of hash
* Request a new review
* Process the comments from the review
}
/* allocates and clears the hash */
-struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
- hashdata_choose_cb choose)
+struct hashtable_t *hash_new(int size, hashdata_choose_cb choose)
{
struct hashtable_t *hash;
hash_init(hash);
- hash->compare = compare;
hash->choose = choose;
return hash;
}
/* adds data to the hashtable. returns 0 on success, -1 on error */
-int hash_add(struct hashtable_t *hash, void *data)
+int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare, void *data)
{
int index;
struct element_t *bucket, *prev_bucket = NULL;
bucket = hash->table[index];
while (bucket != NULL) {
- if (hash->compare(bucket->data, data))
+ if (compare(bucket->data, data))
return -1;
prev_bucket = bucket;
/* finds data, based on the key in keydata. returns the found data on success,
* or NULL on error */
-void *hash_find(struct hashtable_t *hash, void *keydata)
+void *hash_find(struct hashtable_t *hash, hashdata_compare_cb compare,
+ void *keydata)
{
int index;
struct element_t *bucket;
bucket = hash->table[index];
while (bucket != NULL) {
- if (hash->compare(bucket->data, keydata))
+ if (compare(bucket->data, keydata))
return bucket->data;
bucket = bucket->next;
* can remove the used structure yourself, or NULL on error . data could be the
* structure you use with just the key filled, we just need the key for
* comparing. */
-void *hash_remove(struct hashtable_t *hash, void *data)
+void *hash_remove(struct hashtable_t *hash, hashdata_compare_cb compare,
+ void *data)
{
struct hash_it_t hash_it_t;
hash_it_t.prev_bucket = NULL;
while (hash_it_t.bucket != NULL) {
- if (hash->compare(hash_it_t.bucket->data, data)) {
+ if (compare(hash_it_t.bucket->data, data)) {
hash_it_t.first_bucket =
(hash_it_t.bucket ==
hash->table[hash_it_t.index] ?
/* resize the hash, returns the pointer to the new hash or NULL on
* error. removes the old hash on success. */
-struct hashtable_t *hash_resize(struct hashtable_t *hash, int size)
+struct hashtable_t *hash_resize(struct hashtable_t *hash,
+ hashdata_compare_cb compare, int size)
{
struct hashtable_t *new_hash;
struct element_t *bucket;
int i;
/* initialize a new hash with the new size */
- new_hash = hash_new(size, hash->compare, hash->choose);
+ new_hash = hash_new(size, hash->choose);
if (new_hash == NULL)
return NULL;
bucket = hash->table[i];
while (bucket != NULL) {
- hash_add(new_hash, bucket->data);
+ hash_add(new_hash, compare, bucket->data);
bucket = bucket->next;
}
}
.prev_bucket = NULL, \
.first_bucket = NULL }
-
+/* callback to a compare function. should
+ * compare 2 element datas for their keys,
+ * return 0 if same and not 0 if not
+ * same */
typedef int (*hashdata_compare_cb)(void *, void *);
typedef int (*hashdata_choose_cb)(void *, int);
typedef void (*hashdata_free_cb)(void *, void *);
struct element_t **table; /* the hashtable itself, with the buckets */
int elements; /* number of elements registered */
int size; /* size of hashtable */
- hashdata_compare_cb compare;/* callback to a compare function. should
- * compare 2 element datas for their keys,
- * return 0 if same and not 0 if not
- * same */
hashdata_choose_cb choose; /* the hashfunction, should return an index
* based on the key in the data of the first
* argument and the size the second */
};
/* allocates and clears the hash */
-struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
- hashdata_choose_cb choose);
+struct hashtable_t *hash_new(int size, hashdata_choose_cb choose);
/* remove bucket (this might be used in hash_iterate() if you already found the
* bucket you want to delete and don't need the overhead to find it again with
void hash_destroy(struct hashtable_t *hash);
/* adds data to the hashtable. returns 0 on success, -1 on error */
-int hash_add(struct hashtable_t *hash, void *data);
+int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare, void *data);
/* removes data from hash, if found. returns pointer do data on success, so you
* can remove the used structure yourself, or NULL on error . data could be the
* structure you use with just the key filled, we just need the key for
* comparing. */
-void *hash_remove(struct hashtable_t *hash, void *data);
+void *hash_remove(struct hashtable_t *hash, hashdata_compare_cb compare,
+ void *data);
/* finds data, based on the key in keydata. returns the found data on success,
* or NULL on error */
-void *hash_find(struct hashtable_t *hash, void *keydata);
+void *hash_find(struct hashtable_t *hash, hashdata_compare_cb compare,
+ void *keydata);
/* resize the hash, returns the pointer to the new hash or NULL on
* error. removes the old hash on success */
-struct hashtable_t *hash_resize(struct hashtable_t *hash, int size);
+struct hashtable_t *hash_resize(struct hashtable_t *hash,
+ hashdata_compare_cb compare, int size);
/* iterate though the hash. first element is selected with iter_in NULL. use
* the returned iterator to access the elements until hash_it_t returns NULL. */
#include "send.h"
#include "types.h"
#include "hash.h"
+#include "originator.h"
#include "hard-interface.h"
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
+ compare_orig,
icmp_packet->dst));
if (!orig_node)
module_put(THIS_MODULE);
}
-/* returns 1 if they are the same originator */
-
-int compare_orig(void *data1, void *data2)
-{
- return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
-}
-
/* hashfunction to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
int choose_orig(void *data, int32_t size)
void mesh_free(struct net_device *soft_iface);
void inc_module_count(void);
void dec_module_count(void);
-int compare_orig(void *data1, void *data2);
int choose_orig(void *data, int32_t size);
int is_my_mac(uint8_t *addr);
int is_bcast(uint8_t *addr);
return 1;
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- bat_priv->orig_hash = hash_new(128, compare_orig, choose_orig);
+ bat_priv->orig_hash = hash_new(128, choose_orig);
if (!bat_priv->orig_hash)
goto err;
struct hashtable_t *swaphash;
int size;
- orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, addr));
+ orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
+ compare_orig, addr));
if (orig_node)
return orig_node;
if (!orig_node->bcast_own_sum)
goto free_bcast_own;
- if (hash_add(bat_priv->orig_hash, orig_node) < 0)
+ if (hash_add(bat_priv->orig_hash, compare_orig, orig_node) < 0)
goto free_bcast_own_sum;
if (bat_priv->orig_hash->elements * 4 > bat_priv->orig_hash->size) {
- swaphash = hash_resize(bat_priv->orig_hash,
+ swaphash = hash_resize(bat_priv->orig_hash, compare_orig,
bat_priv->orig_hash->size * 2);
if (!swaphash)
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
+
+/* returns 1 if they are the same originator */
+static inline int compare_orig(void *data1, void *data2)
+{
+ return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
+ compare_orig,
icmp_packet->orig));
ret = NET_RX_DROP;
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, icmp_packet->orig));
+ hash_find(bat_priv->orig_hash, compare_orig,
+ icmp_packet->orig));
ret = NET_RX_DROP;
if ((orig_node != NULL) &&
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, icmp_packet->dst));
+ hash_find(bat_priv->orig_hash, compare_orig,
+ icmp_packet->dst));
if ((orig_node != NULL) &&
(orig_node->router != NULL)) {
router_orig->orig, ETH_ALEN) == 0) {
primary_orig_node = router_orig;
} else {
- primary_orig_node = hash_find(bat_priv->orig_hash,
+ primary_orig_node = hash_find(bat_priv->orig_hash, compare_orig,
router_orig->primary_addr);
if (!primary_orig_node)
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, unicast_packet->dest));
+ hash_find(bat_priv->orig_hash, compare_orig,
+ unicast_packet->dest));
router = find_router(bat_priv, orig_node, recv_if);
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, bcast_packet->orig));
+ hash_find(bat_priv->orig_hash, compare_orig,
+ bcast_packet->orig));
if (orig_node == NULL) {
spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
#include "types.h"
#include "vis.h"
#include "aggregation.h"
+#include "originator.h"
static void send_outstanding_bcast_packet(struct work_struct *work);
#include "soft-interface.h"
#include "types.h"
#include "hash.h"
+#include "originator.h"
static void hna_local_purge(struct work_struct *work);
static void _hna_global_del_orig(struct bat_priv *bat_priv,
if (bat_priv->hna_local_hash)
return 1;
- bat_priv->hna_local_hash = hash_new(128, compare_orig, choose_orig);
+ bat_priv->hna_local_hash = hash_new(128, choose_orig);
if (!bat_priv->hna_local_hash)
return 0;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
hna_local_entry =
((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash,
- addr));
+ compare_orig, addr));
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
if (hna_local_entry) {
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
- hash_add(bat_priv->hna_local_hash, hna_local_entry);
+ hash_add(bat_priv->hna_local_hash, compare_orig, hna_local_entry);
bat_priv->num_local_hna++;
atomic_set(&bat_priv->hna_local_changed, 1);
if (bat_priv->hna_local_hash->elements * 4 >
bat_priv->hna_local_hash->size) {
- swaphash = hash_resize(bat_priv->hna_local_hash,
+ swaphash = hash_resize(bat_priv->hna_local_hash, compare_orig,
bat_priv->hna_local_hash->size * 2);
if (!swaphash)
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
hna_global_entry = ((struct hna_global_entry *)
- hash_find(bat_priv->hna_global_hash, addr));
+ hash_find(bat_priv->hna_global_hash,
+ compare_orig, addr));
if (hna_global_entry)
_hna_global_del_orig(bat_priv, hna_global_entry,
bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
hna_local_entry->addr, message);
- hash_remove(bat_priv->hna_local_hash, hna_local_entry->addr);
+ hash_remove(bat_priv->hna_local_hash, compare_orig,
+ hna_local_entry->addr);
_hna_local_del(hna_local_entry, bat_priv);
}
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
hna_local_entry = (struct hna_local_entry *)
- hash_find(bat_priv->hna_local_hash, addr);
+ hash_find(bat_priv->hna_local_hash, compare_orig, addr);
if (hna_local_entry)
hna_local_del(bat_priv, hna_local_entry, message);
if (bat_priv->hna_global_hash)
return 1;
- bat_priv->hna_global_hash = hash_new(128, compare_orig, choose_orig);
+ bat_priv->hna_global_hash = hash_new(128, choose_orig);
if (!bat_priv->hna_global_hash)
return 0;
hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
hna_global_entry = (struct hna_global_entry *)
- hash_find(bat_priv->hna_global_hash, hna_ptr);
+ hash_find(bat_priv->hna_global_hash, compare_orig,
+ hna_ptr);
if (!hna_global_entry) {
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock,
hna_global_entry->addr, orig_node->orig);
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
- hash_add(bat_priv->hna_global_hash, hna_global_entry);
+ hash_add(bat_priv->hna_global_hash, compare_orig,
+ hna_global_entry);
}
hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
hna_local_entry = (struct hna_local_entry *)
- hash_find(bat_priv->hna_local_hash, hna_ptr);
+ hash_find(bat_priv->hna_local_hash, compare_orig,
+ hna_ptr);
if (hna_local_entry)
hna_local_del(bat_priv, hna_local_entry,
if (bat_priv->hna_global_hash->elements * 4 >
bat_priv->hna_global_hash->size) {
- swaphash = hash_resize(bat_priv->hna_global_hash,
+ swaphash = hash_resize(bat_priv->hna_global_hash, compare_orig,
bat_priv->hna_global_hash->size * 2);
if (!swaphash)
hna_global_entry->addr, hna_global_entry->orig_node->orig,
message);
- hash_remove(bat_priv->hna_global_hash, hna_global_entry->addr);
+ hash_remove(bat_priv->hna_global_hash, compare_orig,
+ hna_global_entry->addr);
kfree(hna_global_entry);
}
while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
hna_global_entry = (struct hna_global_entry *)
- hash_find(bat_priv->hna_global_hash, hna_ptr);
+ hash_find(bat_priv->hna_global_hash, compare_orig,
+ hna_ptr);
if ((hna_global_entry) &&
(hna_global_entry->orig_node == orig_node))
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
hna_global_entry = (struct hna_global_entry *)
- hash_find(bat_priv->hna_global_hash, addr);
+ hash_find(bat_priv->hna_global_hash,
+ compare_orig, addr);
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
if (!hna_global_entry)
#include "unicast.h"
#include "send.h"
#include "soft-interface.h"
+#include "originator.h"
#include "hash.h"
#include "translation-table.h"
#include "routing.h"
*new_skb = NULL;
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, unicast_packet->orig));
+ hash_find(bat_priv->orig_hash, compare_orig,
+ unicast_packet->orig));
if (!orig_node) {
pr_debug("couldn't find originator in orig_hash\n");
/* get routing information */
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
+ compare_orig,
ethhdr->h_dest));
/* check for hna host */
#include "soft-interface.h"
#include "hard-interface.h"
#include "hash.h"
+#include "originator.h"
#define MAX_VIS_PACKET_SIZE 1000
sizeof(struct vis_packet));
memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
- old_info = hash_find(bat_priv->vis_hash, &search_elem);
+ old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, &search_elem);
kfree_skb(search_elem.skb_packet);
if (old_info != NULL) {
}
}
/* remove old entry */
- hash_remove(bat_priv->vis_hash, old_info);
+ hash_remove(bat_priv->vis_hash, vis_info_cmp, old_info);
send_list_del(old_info);
kref_put(&old_info->refcount, free_info);
}
recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
/* try to add it */
- if (hash_add(bat_priv->vis_hash, info) < 0) {
+ if (hash_add(bat_priv->vis_hash, vis_info_cmp, info) < 0) {
/* did not work (for some reason) */
kref_put(&old_info->refcount, free_info);
info = NULL;
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
packet = (struct vis_packet *)info->skb_packet->data;
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
+ compare_orig,
packet->target_orig));
if ((!orig_node) || (!orig_node->router))
{
struct vis_packet *packet;
unsigned long flags;
+ int hash_added;
if (bat_priv->vis_hash)
return 1;
spin_lock_irqsave(&bat_priv->vis_hash_lock, flags);
- bat_priv->vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
+ bat_priv->vis_hash = hash_new(256, vis_info_choose);
if (!bat_priv->vis_hash) {
pr_err("Can't initialize vis_hash\n");
goto err;
INIT_LIST_HEAD(&bat_priv->vis_send_list);
- if (hash_add(bat_priv->vis_hash, bat_priv->my_vis_info) < 0) {
+ hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp,
+ bat_priv->my_vis_info);
+ if (hash_added < 0) {
pr_err("Can't add own vis packet into hash\n");
/* not in hash, need to remove it manually. */
kref_put(&bat_priv->my_vis_info->refcount, free_info);