diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2011-01-25 16:52:10 -0500 |
---|---|---|
committer | Marek Lindner <lindner_marek@yahoo.de> | 2011-03-05 06:50:08 -0500 |
commit | 0ede9f41b217d8982ab426e3c8c1b692a280a16f (patch) | |
tree | 3d3379f4614ec898d1db8845fdcbbbf7134f0165 /net/batman-adv | |
parent | ed75ccbe26f4a672a41556120390e67c80a2c441 (diff) |
batman-adv: protect bit operations to count OGMs with spinlock
Reported-by: Linus Lüssing <linus.luessing@saxnet.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/routing.c | 61 | ||||
-rw-r--r-- | net/batman-adv/types.h | 6 |
2 files changed, 33 insertions, 34 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 9185666ab3e0..29a689ac5693 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -155,7 +155,8 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
155 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 155 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
156 | struct hlist_node *node; | 156 | struct hlist_node *node; |
157 | unsigned char total_count; | 157 | unsigned char total_count; |
158 | int ret = 0; | 158 | uint8_t orig_eq_count, neigh_rq_count, tq_own; |
159 | int tq_asym_penalty, ret = 0; | ||
159 | 160 | ||
160 | if (orig_node == orig_neigh_node) { | 161 | if (orig_node == orig_neigh_node) { |
161 | rcu_read_lock(); | 162 | rcu_read_lock(); |
@@ -216,23 +217,25 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
216 | 217 | ||
217 | orig_node->last_valid = jiffies; | 218 | orig_node->last_valid = jiffies; |
218 | 219 | ||
220 | spin_lock_bh(&orig_node->ogm_cnt_lock); | ||
221 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; | ||
222 | neigh_rq_count = neigh_node->real_packet_count; | ||
223 | spin_unlock_bh(&orig_node->ogm_cnt_lock); | ||
224 | |||
219 | /* pay attention to not get a value bigger than 100 % */ | 225 | /* pay attention to not get a value bigger than 100 % */ |
220 | total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] > | 226 | total_count = (orig_eq_count > neigh_rq_count ? |
221 | neigh_node->real_packet_count ? | 227 | neigh_rq_count : orig_eq_count); |
222 | neigh_node->real_packet_count : | ||
223 | orig_neigh_node->bcast_own_sum[if_incoming->if_num]); | ||
224 | 228 | ||
225 | /* if we have too few packets (too less data) we set tq_own to zero */ | 229 | /* if we have too few packets (too less data) we set tq_own to zero */ |
226 | /* if we receive too few packets it is not considered bidirectional */ | 230 | /* if we receive too few packets it is not considered bidirectional */ |
227 | if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || | 231 | if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || |
228 | (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM)) | 232 | (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM)) |
229 | orig_neigh_node->tq_own = 0; | 233 | tq_own = 0; |
230 | else | 234 | else |
231 | /* neigh_node->real_packet_count is never zero as we | 235 | /* neigh_node->real_packet_count is never zero as we |
232 | * only purge old information when getting new | 236 | * only purge old information when getting new |
233 | * information */ | 237 | * information */ |
234 | orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / | 238 | tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count; |
235 | neigh_node->real_packet_count; | ||
236 | 239 | ||
237 | /* | 240 | /* |
238 | * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does | 241 | * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does |
@@ -240,20 +243,16 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
240 | * punishes asymmetric links more. This will give a value | 243 | * punishes asymmetric links more. This will give a value |
241 | * between 0 and TQ_MAX_VALUE | 244 | * between 0 and TQ_MAX_VALUE |
242 | */ | 245 | */ |
243 | orig_neigh_node->tq_asym_penalty = | 246 | tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE * |
244 | TQ_MAX_VALUE - | 247 | (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) * |
245 | (TQ_MAX_VALUE * | 248 | (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) * |
246 | (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) * | 249 | (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) / |
247 | (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) * | 250 | (TQ_LOCAL_WINDOW_SIZE * |
248 | (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) / | 251 | TQ_LOCAL_WINDOW_SIZE * |
249 | (TQ_LOCAL_WINDOW_SIZE * | 252 | TQ_LOCAL_WINDOW_SIZE); |
250 | TQ_LOCAL_WINDOW_SIZE * | 253 | |
251 | TQ_LOCAL_WINDOW_SIZE); | 254 | batman_packet->tq = ((batman_packet->tq * tq_own * tq_asym_penalty) / |
252 | 255 | (TQ_MAX_VALUE * TQ_MAX_VALUE)); | |
253 | batman_packet->tq = ((batman_packet->tq * | ||
254 | orig_neigh_node->tq_own * | ||
255 | orig_neigh_node->tq_asym_penalty) / | ||
256 | (TQ_MAX_VALUE * TQ_MAX_VALUE)); | ||
257 | 256 | ||
258 | bat_dbg(DBG_BATMAN, bat_priv, | 257 | bat_dbg(DBG_BATMAN, bat_priv, |
259 | "bidirectional: " | 258 | "bidirectional: " |
@@ -261,8 +260,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
261 | "real recv = %2i, local tq: %3i, asym_penalty: %3i, " | 260 | "real recv = %2i, local tq: %3i, asym_penalty: %3i, " |
262 | "total tq: %3i\n", | 261 | "total tq: %3i\n", |
263 | orig_node->orig, orig_neigh_node->orig, total_count, | 262 | orig_node->orig, orig_neigh_node->orig, total_count, |
264 | neigh_node->real_packet_count, orig_neigh_node->tq_own, | 263 | neigh_rq_count, tq_own, tq_asym_penalty, batman_packet->tq); |
265 | orig_neigh_node->tq_asym_penalty, batman_packet->tq); | ||
266 | 264 | ||
267 | /* if link has the minimum required transmission quality | 265 | /* if link has the minimum required transmission quality |
268 | * consider it bidirectional */ | 266 | * consider it bidirectional */ |
@@ -559,18 +557,19 @@ static char count_real_packets(struct ethhdr *ethhdr, | |||
559 | char is_duplicate = 0; | 557 | char is_duplicate = 0; |
560 | int32_t seq_diff; | 558 | int32_t seq_diff; |
561 | int need_update = 0; | 559 | int need_update = 0; |
562 | int set_mark; | 560 | int set_mark, ret = -1; |
563 | 561 | ||
564 | orig_node = get_orig_node(bat_priv, batman_packet->orig); | 562 | orig_node = get_orig_node(bat_priv, batman_packet->orig); |
565 | if (!orig_node) | 563 | if (!orig_node) |
566 | return 0; | 564 | return 0; |
567 | 565 | ||
566 | spin_lock_bh(&orig_node->ogm_cnt_lock); | ||
568 | seq_diff = batman_packet->seqno - orig_node->last_real_seqno; | 567 | seq_diff = batman_packet->seqno - orig_node->last_real_seqno; |
569 | 568 | ||
570 | /* signalize caller that the packet is to be dropped. */ | 569 | /* signalize caller that the packet is to be dropped. */ |
571 | if (window_protected(bat_priv, seq_diff, | 570 | if (window_protected(bat_priv, seq_diff, |
572 | &orig_node->batman_seqno_reset)) | 571 | &orig_node->batman_seqno_reset)) |
573 | goto err; | 572 | goto out; |
574 | 573 | ||
575 | rcu_read_lock(); | 574 | rcu_read_lock(); |
576 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | 575 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
@@ -603,12 +602,12 @@ static char count_real_packets(struct ethhdr *ethhdr, | |||
603 | orig_node->last_real_seqno = batman_packet->seqno; | 602 | orig_node->last_real_seqno = batman_packet->seqno; |
604 | } | 603 | } |
605 | 604 | ||
606 | kref_put(&orig_node->refcount, orig_node_free_ref); | 605 | ret = is_duplicate; |
607 | return is_duplicate; | ||
608 | 606 | ||
609 | err: | 607 | out: |
608 | spin_unlock_bh(&orig_node->ogm_cnt_lock); | ||
610 | kref_put(&orig_node->refcount, orig_node_free_ref); | 609 | kref_put(&orig_node->refcount, orig_node_free_ref); |
611 | return -1; | 610 | return ret; |
612 | } | 611 | } |
613 | 612 | ||
614 | void receive_bat_packet(struct ethhdr *ethhdr, | 613 | void receive_bat_packet(struct ethhdr *ethhdr, |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index e0140c65d8f3..9a142760bd9c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -70,8 +70,6 @@ struct orig_node { | |||
70 | struct neigh_node *router; | 70 | struct neigh_node *router; |
71 | unsigned long *bcast_own; | 71 | unsigned long *bcast_own; |
72 | uint8_t *bcast_own_sum; | 72 | uint8_t *bcast_own_sum; |
73 | uint8_t tq_own; | ||
74 | int tq_asym_penalty; | ||
75 | unsigned long last_valid; | 73 | unsigned long last_valid; |
76 | unsigned long bcast_seqno_reset; | 74 | unsigned long bcast_seqno_reset; |
77 | unsigned long batman_seqno_reset; | 75 | unsigned long batman_seqno_reset; |
@@ -89,7 +87,9 @@ struct orig_node { | |||
89 | struct kref refcount; | 87 | struct kref refcount; |
90 | struct bat_priv *bat_priv; | 88 | struct bat_priv *bat_priv; |
91 | unsigned long last_frag_packet; | 89 | unsigned long last_frag_packet; |
92 | spinlock_t ogm_cnt_lock; /* protects ogm counter */ | 90 | spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, |
91 | * neigh_node->real_bits, | ||
92 | * neigh_node->real_packet_count */ | ||
93 | atomic_t bond_candidates; | 93 | atomic_t bond_candidates; |
94 | struct list_head bond_list; | 94 | struct list_head bond_list; |
95 | }; | 95 | }; |