| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1 | /* | 
| Sven Eckelmann | 64afe35 | 2011-01-27 10:38:15 +0100 | [diff] [blame] | 2 |  * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 3 |  * | 
 | 4 |  * Marek Lindner, Simon Wunderlich | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or | 
 | 7 |  * modify it under the terms of version 2 of the GNU General Public | 
 | 8 |  * License as published by the Free Software Foundation. | 
 | 9 |  * | 
 | 10 |  * This program is distributed in the hope that it will be useful, but | 
 | 11 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 
 | 13 |  * General Public License for more details. | 
 | 14 |  * | 
 | 15 |  * You should have received a copy of the GNU General Public License | 
 | 16 |  * along with this program; if not, write to the Free Software | 
 | 17 |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 
 | 18 |  * 02110-1301, USA | 
 | 19 |  * | 
 | 20 |  */ | 
 | 21 |  | 
 | 22 | #ifndef _NET_BATMAN_ADV_ORIGINATOR_H_ | 
 | 23 | #define _NET_BATMAN_ADV_ORIGINATOR_H_ | 
 | 24 |  | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 25 | #include "hash.h" | 
 | 26 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 27 | int originator_init(struct bat_priv *bat_priv); | 
 | 28 | void originator_free(struct bat_priv *bat_priv); | 
 | 29 | void purge_orig_ref(struct bat_priv *bat_priv); | 
| Marek Lindner | 7b36e8e | 2011-02-18 12:28:10 +0000 | [diff] [blame] | 30 | void orig_node_free_ref(struct orig_node *orig_node); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 31 | struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); | 
| Marek Lindner | a8e7f4b | 2010-12-12 21:57:10 +0000 | [diff] [blame] | 32 | struct neigh_node *create_neighbor(struct orig_node *orig_node, | 
 | 33 | 				   struct orig_node *orig_neigh_node, | 
 | 34 | 				   uint8_t *neigh, | 
| Marek Lindner | e6c10f4 | 2011-02-18 12:33:20 +0000 | [diff] [blame] | 35 | 				   struct hard_iface *if_incoming); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 36 | void neigh_node_free_ref(struct neigh_node *neigh_node); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 37 | int orig_seq_print_text(struct seq_file *seq, void *offset); | 
| Marek Lindner | e6c10f4 | 2011-02-18 12:33:20 +0000 | [diff] [blame] | 38 | int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); | 
 | 39 | int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 40 |  | 
 | 41 |  | 
 | 42 | /* returns 1 if they are the same originator */ | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 43 | static inline int compare_orig(struct hlist_node *node, void *data2) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 44 | { | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 45 | 	void *data1 = container_of(node, struct orig_node, hash_entry); | 
 | 46 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 47 | 	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 
 | 48 | } | 
 | 49 |  | 
 | 50 | /* hashfunction to choose an entry in a hash table of given size */ | 
 | 51 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ | 
 | 52 | static inline int choose_orig(void *data, int32_t size) | 
 | 53 | { | 
 | 54 | 	unsigned char *key = data; | 
 | 55 | 	uint32_t hash = 0; | 
 | 56 | 	size_t i; | 
 | 57 |  | 
 | 58 | 	for (i = 0; i < 6; i++) { | 
 | 59 | 		hash += key[i]; | 
 | 60 | 		hash += (hash << 10); | 
 | 61 | 		hash ^= (hash >> 6); | 
 | 62 | 	} | 
 | 63 |  | 
 | 64 | 	hash += (hash << 3); | 
 | 65 | 	hash ^= (hash >> 11); | 
 | 66 | 	hash += (hash << 15); | 
 | 67 |  | 
 | 68 | 	return hash % size; | 
 | 69 | } | 
 | 70 |  | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 71 | static inline struct orig_node *orig_hash_find(struct bat_priv *bat_priv, | 
 | 72 | 					       void *data) | 
 | 73 | { | 
 | 74 | 	struct hashtable_t *hash = bat_priv->orig_hash; | 
 | 75 | 	struct hlist_head *head; | 
 | 76 | 	struct hlist_node *node; | 
 | 77 | 	struct orig_node *orig_node, *orig_node_tmp = NULL; | 
 | 78 | 	int index; | 
 | 79 |  | 
 | 80 | 	if (!hash) | 
 | 81 | 		return NULL; | 
 | 82 |  | 
 | 83 | 	index = choose_orig(data, hash->size); | 
 | 84 | 	head = &hash->table[index]; | 
 | 85 |  | 
 | 86 | 	rcu_read_lock(); | 
 | 87 | 	hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 
 | 88 | 		if (!compare_eth(orig_node, data)) | 
 | 89 | 			continue; | 
 | 90 |  | 
| Marek Lindner | 7b36e8e | 2011-02-18 12:28:10 +0000 | [diff] [blame] | 91 | 		if (!atomic_inc_not_zero(&orig_node->refcount)) | 
 | 92 | 			continue; | 
 | 93 |  | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 94 | 		orig_node_tmp = orig_node; | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 95 | 		break; | 
 | 96 | 	} | 
 | 97 | 	rcu_read_unlock(); | 
 | 98 |  | 
 | 99 | 	return orig_node_tmp; | 
 | 100 | } | 
 | 101 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 102 | #endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */ |