aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2012-02-04 11:34:52 -0500
committerAntonio Quartulli <ordex@autistici.org>2012-04-11 08:28:58 -0400
commit0079d2cef1514422668c7beedd61bfde5aa2c146 (patch)
tree64d118360835eb1abfa9546ce3cac99c8db9ce79 /net
parentc1faead3335608d9c9bb58e07bbf9663d53d4b26 (diff)
batman-adv: Replace bitarray operations with bitmap
bitarray.c consists mostly of functionality that is already available as part of the standard kernel API. batman-adv could use architecture optimized code and reduce the binary size by switching to the standard functions. Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/bat_iv_ogm.c15
-rw-r--r--net/batman-adv/bitarray.c118
-rw-r--r--net/batman-adv/bitarray.h26
-rw-r--r--net/batman-adv/main.h2
-rw-r--r--net/batman-adv/routing.c6
-rw-r--r--net/batman-adv/types.h4
6 files changed, 41 insertions, 130 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index a6d5d63fb6ad..fab1071f601e 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -850,9 +850,9 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
850 hlist_for_each_entry_rcu(tmp_neigh_node, node, 850 hlist_for_each_entry_rcu(tmp_neigh_node, node,
851 &orig_node->neigh_list, list) { 851 &orig_node->neigh_list, list) {
852 852
853 is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, 853 is_duplicate |= bat_test_bit(tmp_neigh_node->real_bits,
854 orig_node->last_real_seqno, 854 orig_node->last_real_seqno,
855 batman_ogm_packet->seqno); 855 batman_ogm_packet->seqno);
856 856
857 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && 857 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
858 (tmp_neigh_node->if_incoming == if_incoming)) 858 (tmp_neigh_node->if_incoming == if_incoming))
@@ -866,7 +866,8 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
866 seq_diff, set_mark); 866 seq_diff, set_mark);
867 867
868 tmp_neigh_node->real_packet_count = 868 tmp_neigh_node->real_packet_count =
869 bit_packet_count(tmp_neigh_node->real_bits); 869 bitmap_weight(tmp_neigh_node->real_bits,
870 TQ_LOCAL_WINDOW_SIZE);
870 } 871 }
871 rcu_read_unlock(); 872 rcu_read_unlock();
872 873
@@ -998,11 +999,11 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
998 999
999 spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); 1000 spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
1000 word = &(orig_neigh_node->bcast_own[offset]); 1001 word = &(orig_neigh_node->bcast_own[offset]);
1001 bit_mark(word, 1002 bat_set_bit(word,
1002 if_incoming_seqno - 1003 if_incoming_seqno -
1003 batman_ogm_packet->seqno - 2); 1004 batman_ogm_packet->seqno - 2);
1004 orig_neigh_node->bcast_own_sum[if_incoming->if_num] = 1005 orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
1005 bit_packet_count(word); 1006 bitmap_weight(word, TQ_LOCAL_WINDOW_SIZE);
1006 spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); 1007 spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
1007 } 1008 }
1008 1009
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index 6d0aa216b232..07ae6e1b8aca 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -24,100 +24,13 @@
24 24
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26 26
27/* returns true if the corresponding bit in the given seq_bits indicates true
28 * and curr_seqno is within range of last_seqno */
29int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno,
30 uint32_t curr_seqno)
31{
32 int32_t diff, word_offset, word_num;
33
34 diff = last_seqno - curr_seqno;
35 if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) {
36 return 0;
37 } else {
38 /* which word */
39 word_num = (last_seqno - curr_seqno) / WORD_BIT_SIZE;
40 /* which position in the selected word */
41 word_offset = (last_seqno - curr_seqno) % WORD_BIT_SIZE;
42
43 if (test_bit(word_offset, &seq_bits[word_num]))
44 return 1;
45 else
46 return 0;
47 }
48}
49
50/* turn corresponding bit on, so we can remember that we got the packet */
51void bit_mark(unsigned long *seq_bits, int32_t n)
52{
53 int32_t word_offset, word_num;
54
55 /* if too old, just drop it */
56 if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE)
57 return;
58
59 /* which word */
60 word_num = n / WORD_BIT_SIZE;
61 /* which position in the selected word */
62 word_offset = n % WORD_BIT_SIZE;
63
64 set_bit(word_offset, &seq_bits[word_num]); /* turn the position on */
65}
66
67/* shift the packet array by n places. */ 27/* shift the packet array by n places. */
68static void bit_shift(unsigned long *seq_bits, int32_t n) 28static void bat_bitmap_shift_left(unsigned long *seq_bits, int32_t n)
69{ 29{
70 int32_t word_offset, word_num;
71 int32_t i;
72
73 if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE) 30 if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE)
74 return; 31 return;
75 32
76 word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */ 33 bitmap_shift_left(seq_bits, seq_bits, n, TQ_LOCAL_WINDOW_SIZE);
77 word_num = n / WORD_BIT_SIZE; /* shift over how much (full) words */
78
79 for (i = NUM_WORDS - 1; i > word_num; i--) {
80 /* going from old to new, so we don't overwrite the data we copy
81 * from.
82 *
83 * left is high, right is low: FEDC BA98 7654 3210
84 * ^^ ^^
85 * vvvv
86 * ^^^^ = from, vvvvv =to, we'd have word_num==1 and
87 * word_offset==WORD_BIT_SIZE/2 ????? in this example.
88 * (=24 bits)
89 *
90 * our desired output would be: 9876 5432 1000 0000
91 * */
92
93 seq_bits[i] =
94 (seq_bits[i - word_num] << word_offset) +
95 /* take the lower port from the left half, shift it left
96 * to its final position */
97 (seq_bits[i - word_num - 1] >>
98 (WORD_BIT_SIZE-word_offset));
99 /* and the upper part of the right half and shift it left to
100 * its position */
101 /* for our example that would be: word[0] = 9800 + 0076 =
102 * 9876 */
103 }
104 /* now for our last word, i==word_num, we only have its "left" half.
105 * that's the 1000 word in our example.*/
106
107 seq_bits[i] = (seq_bits[i - word_num] << word_offset);
108
109 /* pad the rest with 0, if there is anything */
110 i--;
111
112 for (; i >= 0; i--)
113 seq_bits[i] = 0;
114}
115
116static void bit_reset_window(unsigned long *seq_bits)
117{
118 int i;
119 for (i = 0; i < NUM_WORDS; i++)
120 seq_bits[i] = 0;
121} 34}
122 35
123 36
@@ -137,7 +50,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits,
137 50
138 if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) { 51 if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) {
139 if (set_mark) 52 if (set_mark)
140 bit_mark(seq_bits, -seq_num_diff); 53 bat_set_bit(seq_bits, -seq_num_diff);
141 return 0; 54 return 0;
142 } 55 }
143 56
@@ -145,10 +58,10 @@ int bit_get_packet(void *priv, unsigned long *seq_bits,
145 * set the mark if required */ 58 * set the mark if required */
146 59
147 if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) { 60 if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) {
148 bit_shift(seq_bits, seq_num_diff); 61 bat_bitmap_shift_left(seq_bits, seq_num_diff);
149 62
150 if (set_mark) 63 if (set_mark)
151 bit_mark(seq_bits, 0); 64 bat_set_bit(seq_bits, 0);
152 return 1; 65 return 1;
153 } 66 }
154 67
@@ -159,9 +72,9 @@ int bit_get_packet(void *priv, unsigned long *seq_bits,
159 bat_dbg(DBG_BATMAN, bat_priv, 72 bat_dbg(DBG_BATMAN, bat_priv,
160 "We missed a lot of packets (%i) !\n", 73 "We missed a lot of packets (%i) !\n",
161 seq_num_diff - 1); 74 seq_num_diff - 1);
162 bit_reset_window(seq_bits); 75 bitmap_zero(seq_bits, TQ_LOCAL_WINDOW_SIZE);
163 if (set_mark) 76 if (set_mark)
164 bit_mark(seq_bits, 0); 77 bat_set_bit(seq_bits, 0);
165 return 1; 78 return 1;
166 } 79 }
167 80
@@ -176,9 +89,9 @@ int bit_get_packet(void *priv, unsigned long *seq_bits,
176 bat_dbg(DBG_BATMAN, bat_priv, 89 bat_dbg(DBG_BATMAN, bat_priv,
177 "Other host probably restarted!\n"); 90 "Other host probably restarted!\n");
178 91
179 bit_reset_window(seq_bits); 92 bitmap_zero(seq_bits, TQ_LOCAL_WINDOW_SIZE);
180 if (set_mark) 93 if (set_mark)
181 bit_mark(seq_bits, 0); 94 bat_set_bit(seq_bits, 0);
182 95
183 return 1; 96 return 1;
184 } 97 }
@@ -186,16 +99,3 @@ int bit_get_packet(void *priv, unsigned long *seq_bits,
186 /* never reached */ 99 /* never reached */
187 return 0; 100 return 0;
188} 101}
189
190/* count the hamming weight, how many good packets did we receive? just count
191 * the 1's.
192 */
193int bit_packet_count(const unsigned long *seq_bits)
194{
195 int i, hamming = 0;
196
197 for (i = 0; i < NUM_WORDS; i++)
198 hamming += hweight_long(seq_bits[i]);
199
200 return hamming;
201}
diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h
index c6135728a680..1835c15cda41 100644
--- a/net/batman-adv/bitarray.h
+++ b/net/batman-adv/bitarray.h
@@ -22,23 +22,33 @@
22#ifndef _NET_BATMAN_ADV_BITARRAY_H_ 22#ifndef _NET_BATMAN_ADV_BITARRAY_H_
23#define _NET_BATMAN_ADV_BITARRAY_H_ 23#define _NET_BATMAN_ADV_BITARRAY_H_
24 24
25#define WORD_BIT_SIZE (sizeof(unsigned long) * 8)
26
27/* returns true if the corresponding bit in the given seq_bits indicates true 25/* returns true if the corresponding bit in the given seq_bits indicates true
28 * and curr_seqno is within range of last_seqno */ 26 * and curr_seqno is within range of last_seqno */
29int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno, 27static inline int bat_test_bit(const unsigned long *seq_bits,
30 uint32_t curr_seqno); 28 uint32_t last_seqno, uint32_t curr_seqno)
29{
30 int32_t diff;
31
32 diff = last_seqno - curr_seqno;
33 if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE)
34 return 0;
35 else
36 return test_bit(diff, seq_bits);
37}
31 38
32/* turn corresponding bit on, so we can remember that we got the packet */ 39/* turn corresponding bit on, so we can remember that we got the packet */
33void bit_mark(unsigned long *seq_bits, int32_t n); 40static inline void bat_set_bit(unsigned long *seq_bits, int32_t n)
41{
42 /* if too old, just drop it */
43 if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE)
44 return;
34 45
46 set_bit(n, seq_bits); /* turn the position on */
47}
35 48
36/* receive and process one packet, returns 1 if received seq_num is considered 49/* receive and process one packet, returns 1 if received seq_num is considered
37 * new, 0 if old */ 50 * new, 0 if old */
38int bit_get_packet(void *priv, unsigned long *seq_bits, 51int bit_get_packet(void *priv, unsigned long *seq_bits,
39 int32_t seq_num_diff, int set_mark); 52 int32_t seq_num_diff, int set_mark);
40 53
41/* count the hamming weight, how many good packets did we receive? */
42int bit_packet_count(const unsigned long *seq_bits);
43
44#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */ 54#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 94fa1c2393a6..0a20a19197aa 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -65,7 +65,7 @@
65 65
66#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */ 66#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
67 67
68#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) 68#define NUM_WORDS BITS_TO_LONGS(TQ_LOCAL_WINDOW_SIZE)
69 69
70#define LOG_BUF_LEN 8192 /* has to be a power of 2 */ 70#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
71 71
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 7f8e15899417..b0370e3c59e8 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -52,7 +52,7 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
52 52
53 bit_get_packet(bat_priv, word, 1, 0); 53 bit_get_packet(bat_priv, word, 1, 0);
54 orig_node->bcast_own_sum[hard_iface->if_num] = 54 orig_node->bcast_own_sum[hard_iface->if_num] =
55 bit_packet_count(word); 55 bitmap_weight(word, TQ_LOCAL_WINDOW_SIZE);
56 spin_unlock_bh(&orig_node->ogm_cnt_lock); 56 spin_unlock_bh(&orig_node->ogm_cnt_lock);
57 } 57 }
58 rcu_read_unlock(); 58 rcu_read_unlock();
@@ -1047,8 +1047,8 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
1047 spin_lock_bh(&orig_node->bcast_seqno_lock); 1047 spin_lock_bh(&orig_node->bcast_seqno_lock);
1048 1048
1049 /* check whether the packet is a duplicate */ 1049 /* check whether the packet is a duplicate */
1050 if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, 1050 if (bat_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno,
1051 ntohl(bcast_packet->seqno))) 1051 ntohl(bcast_packet->seqno)))
1052 goto spin_unlock; 1052 goto spin_unlock;
1053 1053
1054 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; 1054 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 302efb523475..24c8a31a3d91 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -90,7 +90,7 @@ struct orig_node {
90 bool tt_poss_change; 90 bool tt_poss_change;
91 uint32_t last_real_seqno; 91 uint32_t last_real_seqno;
92 uint8_t last_ttl; 92 uint8_t last_ttl;
93 unsigned long bcast_bits[NUM_WORDS]; 93 DECLARE_BITMAP(bcast_bits, TQ_LOCAL_WINDOW_SIZE);
94 uint32_t last_bcast_seqno; 94 uint32_t last_bcast_seqno;
95 struct hlist_head neigh_list; 95 struct hlist_head neigh_list;
96 struct list_head frag_list; 96 struct list_head frag_list;
@@ -132,7 +132,7 @@ struct neigh_node {
132 uint8_t last_ttl; 132 uint8_t last_ttl;
133 struct list_head bonding_list; 133 struct list_head bonding_list;
134 unsigned long last_valid; 134 unsigned long last_valid;
135 unsigned long real_bits[NUM_WORDS]; 135 DECLARE_BITMAP(real_bits, TQ_LOCAL_WINDOW_SIZE);
136 atomic_t refcount; 136 atomic_t refcount;
137 struct rcu_head rcu; 137 struct rcu_head rcu;
138 struct orig_node *orig_node; 138 struct orig_node *orig_node;