* remove own list functionality from hash
* use hlist_head, hlist_node 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_choose_cb choose)
+struct hashtable_t *hash_new(int size)
{
struct hashtable_t *hash;
hash_init(hash);
- hash->choose = choose;
-
return hash;
}
/* adds data to the hashtable. returns 0 on success, -1 on error */
-int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare, void *data)
+int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare,
+ hashdata_choose_cb choose, void *data)
{
int index;
struct element_t *bucket, *prev_bucket = NULL;
if (!hash)
return -1;
- index = hash->choose(data, hash->size);
+ index = choose(data, hash->size);
bucket = hash->table[index];
while (bucket != NULL) {
/* 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, hashdata_compare_cb compare,
- void *keydata)
+ hashdata_choose_cb choose, void *keydata)
{
int index;
struct element_t *bucket;
if (!hash)
return NULL;
- index = hash->choose(keydata , hash->size);
+ index = choose(keydata , hash->size);
bucket = hash->table[index];
while (bucket != NULL) {
* structure you use with just the key filled, we just need the key for
* comparing. */
void *hash_remove(struct hashtable_t *hash, hashdata_compare_cb compare,
- void *data)
+ hashdata_choose_cb choose, void *data)
{
struct hash_it_t hash_it_t;
- hash_it_t.index = hash->choose(data, hash->size);
+ hash_it_t.index = choose(data, hash->size);
hash_it_t.bucket = hash->table[hash_it_t.index];
hash_it_t.prev_bucket = NULL;
/* 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,
- hashdata_compare_cb compare, int size)
+ hashdata_compare_cb compare,
+ hashdata_choose_cb choose, 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->choose);
+ new_hash = hash_new(size);
if (new_hash == NULL)
return NULL;
bucket = hash->table[i];
while (bucket != NULL) {
- hash_add(new_hash, compare, bucket->data);
+ hash_add(new_hash, compare, choose, bucket->data);
bucket = bucket->next;
}
}
* return 0 if same and not 0 if not
* same */
typedef int (*hashdata_compare_cb)(void *, void *);
+
+/* the hashfunction, should return an index
+ * based on the key in the data of the first
+ * argument and the size the second */
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_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_choose_cb choose);
+struct hashtable_t *hash_new(int size);
/* 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, hashdata_compare_cb compare, void *data);
+int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare,
+ hashdata_choose_cb choose, 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, hashdata_compare_cb compare,
- void *data);
+ hashdata_choose_cb choose, 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, hashdata_compare_cb compare,
- void *keydata);
+ hashdata_choose_cb choose, 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,
- hashdata_compare_cb compare, int size);
+ hashdata_compare_cb compare,
+ hashdata_choose_cb choose, 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. */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
- compare_orig,
+ compare_orig, choose_orig,
icmp_packet->dst));
if (!orig_node)
module_put(THIS_MODULE);
}
-/* 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)
-{
- unsigned char *key = data;
- uint32_t hash = 0;
- size_t i;
-
- for (i = 0; i < 6; i++) {
- hash += key[i];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
-
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash % size;
-}
-
int is_my_mac(uint8_t *addr)
{
struct batman_if *batman_if;
void mesh_free(struct net_device *soft_iface);
void inc_module_count(void);
void dec_module_count(void);
-int choose_orig(void *data, int32_t size);
int is_my_mac(uint8_t *addr);
int is_bcast(uint8_t *addr);
int is_mcast(uint8_t *addr);
return 1;
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- bat_priv->orig_hash = hash_new(128, choose_orig);
+ bat_priv->orig_hash = hash_new(128);
if (!bat_priv->orig_hash)
goto err;
struct orig_node *orig_node;
struct hashtable_t *swaphash;
int size;
+ int hash_added;
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
- compare_orig, addr));
+ compare_orig, choose_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, compare_orig, orig_node) < 0)
+ hash_added = hash_add(bat_priv->orig_hash, compare_orig, choose_orig,
+ orig_node);
+ if (hash_added < 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, compare_orig,
+ choose_orig,
bat_priv->orig_hash->size * 2);
if (!swaphash)
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 */
+static inline int choose_orig(void *data, int32_t size)
+{
+ unsigned char *key = data;
+ uint32_t hash = 0;
+ size_t i;
+
+ for (i = 0; i < 6; i++) {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash % size;
+}
+
#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,
+ compare_orig, choose_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, compare_orig,
+ hash_find(bat_priv->orig_hash, compare_orig, choose_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, compare_orig,
+ hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
icmp_packet->dst));
if ((orig_node != NULL) &&
primary_orig_node = router_orig;
} else {
primary_orig_node = hash_find(bat_priv->orig_hash, compare_orig,
- router_orig->primary_addr);
+ choose_orig,
+ router_orig->primary_addr);
if (!primary_orig_node)
return orig_node->router;
/* 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,
+ hash_find(bat_priv->orig_hash, compare_orig, choose_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, compare_orig,
+ hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
bcast_packet->orig));
if (orig_node == NULL) {
if (bat_priv->hna_local_hash)
return 1;
- bat_priv->hna_local_hash = hash_new(128, choose_orig);
+ bat_priv->hna_local_hash = hash_new(128);
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,
- compare_orig, addr));
+ compare_orig, choose_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, compare_orig, hna_local_entry);
+ hash_add(bat_priv->hna_local_hash, compare_orig, choose_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, compare_orig,
+ choose_orig,
bat_priv->hna_local_hash->size * 2);
if (!swaphash)
hna_global_entry = ((struct hna_global_entry *)
hash_find(bat_priv->hna_global_hash,
- compare_orig, addr));
+ compare_orig, choose_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, compare_orig,
+ hash_remove(bat_priv->hna_local_hash, compare_orig, choose_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, compare_orig, addr);
+ hash_find(bat_priv->hna_local_hash, compare_orig, choose_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, choose_orig);
+ bat_priv->hna_global_hash = hash_new(128);
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, compare_orig,
- hna_ptr);
+ choose_orig, hna_ptr);
if (!hna_global_entry) {
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock,
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
hash_add(bat_priv->hna_global_hash, compare_orig,
- hna_global_entry);
+ choose_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, compare_orig,
- hna_ptr);
+ choose_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, compare_orig,
+ choose_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, compare_orig,
+ hash_remove(bat_priv->hna_global_hash, compare_orig, choose_orig,
hna_global_entry->addr);
kfree(hna_global_entry);
}
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, compare_orig,
- hna_ptr);
+ choose_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,
- compare_orig, addr);
+ compare_orig, choose_orig, addr);
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
if (!hna_global_entry)
*new_skb = NULL;
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, compare_orig,
+ hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
unicast_packet->orig));
if (!orig_node) {
/* get routing information */
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
compare_orig,
+ choose_orig,
ethhdr->h_dest));
/* check for hna host */
struct vis_packet *search_packet, *old_packet;
struct vis_info search_elem;
struct vis_packet *packet;
+ int hash_added;
*is_new = 0;
/* sanity check */
sizeof(struct vis_packet));
memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
- old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, &search_elem);
+ old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
+ &search_elem);
kfree_skb(search_elem.skb_packet);
if (old_info != NULL) {
}
}
/* remove old entry */
- hash_remove(bat_priv->vis_hash, vis_info_cmp, old_info);
+ hash_remove(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
+ 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, vis_info_cmp, info) < 0) {
+ hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
+ info);
+ if (hash_added < 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,
+ compare_orig, choose_orig,
packet->target_orig));
if ((!orig_node) || (!orig_node->router))
spin_lock_irqsave(&bat_priv->vis_hash_lock, flags);
- bat_priv->vis_hash = hash_new(256, vis_info_choose);
+ bat_priv->vis_hash = hash_new(256);
if (!bat_priv->vis_hash) {
pr_err("Can't initialize vis_hash\n");
goto err;
INIT_LIST_HEAD(&bat_priv->vis_send_list);
- hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp,
+ hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
bat_priv->my_vis_info);
if (hash_added < 0) {
pr_err("Can't add own vis packet into hash\n");