Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Staging: batman-adv: Split originator handling parts out of routing.c

Bug found and fixed in origional version by Linus Luessing.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Linus Luessing <linus.luessing@web.de>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Andrew Lunn and committed by
Greg Kroah-Hartman
8a2e042c 4088c7ca

+289 -221
+1 -1
drivers/staging/batman-adv/Makefile
··· 19 19 # 20 20 21 21 obj-m += batman-adv.o 22 - batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o 22 + batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
+1
drivers/staging/batman-adv/main.c
··· 23 23 #include "proc.h" 24 24 #include "routing.h" 25 25 #include "send.h" 26 + #include "originator.h" 26 27 #include "soft-interface.h" 27 28 #include "device.h" 28 29 #include "translation-table.h"
+243
drivers/staging/batman-adv/originator.c
··· 1 + /* 2 + * Copyright (C) 2009 B.A.T.M.A.N. contributors: 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 + /* increase the reference counter for this originator */ 23 + 24 + #include "main.h" 25 + #include "originator.h" 26 + #include "hash.h" 27 + #include "translation-table.h" 28 + #include "routing.h" 29 + 30 + 31 + static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); 32 + 33 + static void start_purge_timer(void) 34 + { 35 + queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ); 36 + } 37 + 38 + int originator_init(void) 39 + { 40 + if (orig_hash) 41 + return 1; 42 + 43 + spin_lock(&orig_hash_lock); 44 + orig_hash = hash_new(128, compare_orig, choose_orig); 45 + 46 + if (!orig_hash) 47 + goto err; 48 + 49 + spin_unlock(&orig_hash_lock); 50 + start_purge_timer(); 51 + return 1; 52 + 53 + err: 54 + spin_unlock(&orig_hash_lock); 55 + return 0; 56 + } 57 + 58 + void originator_free(void) 59 + { 60 + if (!orig_hash) 61 + return; 62 + 63 + cancel_delayed_work_sync(&purge_orig_wq); 64 + 65 + spin_lock(&orig_hash_lock); 66 + hash_delete(orig_hash, free_orig_node); 67 + orig_hash = NULL; 68 + spin_unlock(&orig_hash_lock); 69 + } 70 + 71 + struct neigh_node * 72 + create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, 73 + uint8_t *neigh, struct batman_if *if_incoming) 74 + { 75 + struct neigh_node *neigh_node; 76 + 77 + bat_dbg(DBG_BATMAN, "Creating new last-hop neighbour of originator\n"); 78 + 79 + neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC); 80 + memset(neigh_node, 0, sizeof(struct neigh_node)); 81 + INIT_LIST_HEAD(&neigh_node->list); 82 + 83 + memcpy(neigh_node->addr, neigh, ETH_ALEN); 84 + neigh_node->orig_node = orig_neigh_node; 85 + neigh_node->if_incoming = if_incoming; 86 + 87 + list_add_tail(&neigh_node->list, &orig_node->neigh_list); 88 + return neigh_node; 89 + } 90 + 91 + void free_orig_node(void *data) 92 + { 93 + struct list_head *list_pos, *list_pos_tmp; 94 + struct neigh_node *neigh_node; 95 + struct orig_node *orig_node = (struct orig_node *)data; 96 + 97 + /* for all neighbours towards this originator ... */ 98 + list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 99 + neigh_node = list_entry(list_pos, struct neigh_node, list); 100 + 101 + list_del(list_pos); 102 + kfree(neigh_node); 103 + } 104 + 105 + hna_global_del_orig(orig_node, "originator timed out"); 106 + 107 + kfree(orig_node->bcast_own); 108 + kfree(orig_node->bcast_own_sum); 109 + kfree(orig_node); 110 + } 111 + 112 + /* this function finds or creates an originator entry for the given 113 + * address if it does not exits */ 114 + struct orig_node *get_orig_node(uint8_t *addr) 115 + { 116 + struct orig_node *orig_node; 117 + struct hashtable_t *swaphash; 118 + char orig_str[ETH_STR_LEN]; 119 + int size; 120 + 121 + orig_node = ((struct orig_node *)hash_find(orig_hash, addr)); 122 + 123 + if (orig_node != NULL) 124 + return orig_node; 125 + 126 + addr_to_string(orig_str, addr); 127 + bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str); 128 + 129 + orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC); 130 + memset(orig_node, 0, sizeof(struct orig_node)); 131 + INIT_LIST_HEAD(&orig_node->neigh_list); 132 + 133 + memcpy(orig_node->orig, addr, ETH_ALEN); 134 + orig_node->router = NULL; 135 + orig_node->batman_if = NULL; 136 + orig_node->hna_buff = NULL; 137 + 138 + size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS; 139 + 140 + orig_node->bcast_own = kmalloc(size, GFP_ATOMIC); 141 + memset(orig_node->bcast_own, 0, size); 142 + 143 + size = num_ifs * sizeof(uint8_t); 144 + orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC); 145 + memset(orig_node->bcast_own_sum, 0, size); 146 + 147 + hash_add(orig_hash, orig_node); 148 + 149 + if (orig_hash->elements * 4 > orig_hash->size) { 150 + swaphash = hash_resize(orig_hash, orig_hash->size * 2); 151 + 152 + if (swaphash == NULL) 153 + printk(KERN_ERR 154 + "batman-adv:Couldn't resize orig hash table \n"); 155 + else 156 + orig_hash = swaphash; 157 + } 158 + 159 + return orig_node; 160 + } 161 + 162 + static bool purge_orig_neigbours(struct orig_node *orig_node, 163 + struct neigh_node **best_neigh_node) 164 + { 165 + struct list_head *list_pos, *list_pos_tmp; 166 + char neigh_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; 167 + struct neigh_node *neigh_node; 168 + bool neigh_purged = false; 169 + 170 + *best_neigh_node = NULL; 171 + 172 + 173 + /* for all neighbours towards this originator ... */ 174 + list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 175 + neigh_node = list_entry(list_pos, struct neigh_node, list); 176 + 177 + if (time_after(jiffies, 178 + (neigh_node->last_valid + 179 + ((PURGE_TIMEOUT * HZ) / 1000)))) { 180 + 181 + addr_to_string(neigh_str, neigh_node->addr); 182 + addr_to_string(orig_str, orig_node->orig); 183 + bat_dbg(DBG_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ)); 184 + 185 + neigh_purged = true; 186 + list_del(list_pos); 187 + kfree(neigh_node); 188 + } else { 189 + if ((*best_neigh_node == NULL) || 190 + (neigh_node->tq_avg > (*best_neigh_node)->tq_avg)) 191 + *best_neigh_node = neigh_node; 192 + } 193 + } 194 + return neigh_purged; 195 + } 196 + 197 + 198 + static bool purge_orig_node(struct orig_node *orig_node) 199 + { 200 + struct neigh_node *best_neigh_node; 201 + char orig_str[ETH_STR_LEN]; 202 + 203 + addr_to_string(orig_str, orig_node->orig); 204 + 205 + if (time_after(jiffies, 206 + (orig_node->last_valid + 207 + ((2 * PURGE_TIMEOUT * HZ) / 1000)))) { 208 + 209 + bat_dbg(DBG_BATMAN, 210 + "Originator timeout: originator %s, last_valid %lu\n", 211 + orig_str, (orig_node->last_valid / HZ)); 212 + return true; 213 + } else { 214 + if (purge_orig_neigbours(orig_node, &best_neigh_node)) 215 + update_routes(orig_node, best_neigh_node, 216 + orig_node->hna_buff, 217 + orig_node->hna_buff_len); 218 + } 219 + return false; 220 + } 221 + 222 + void purge_orig(struct work_struct *work) 223 + { 224 + struct hash_it_t *hashit = NULL; 225 + struct orig_node *orig_node; 226 + 227 + spin_lock(&orig_hash_lock); 228 + 229 + /* for all origins... */ 230 + while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { 231 + orig_node = hashit->bucket->data; 232 + if (purge_orig_node(orig_node)) { 233 + hash_remove_bucket(orig_hash, hashit); 234 + free_orig_node(orig_node); 235 + } 236 + } 237 + 238 + spin_unlock(&orig_hash_lock); 239 + 240 + start_purge_timer(); 241 + } 242 + 243 +
+31
drivers/staging/batman-adv/originator.h
··· 1 + /* 2 + * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: 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 + int originator_init(void); 23 + void free_orig_node(void *data); 24 + void originator_free(void); 25 + void purge_orig(struct work_struct *work); 26 + struct orig_node *orig_find(char *mac); 27 + struct orig_node *get_orig_node(uint8_t *addr); 28 + struct neigh_node * 29 + create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, 30 + uint8_t *neigh, struct batman_if *if_incoming); 31 +
+6 -215
drivers/staging/batman-adv/routing.c
··· 22 22 #include "main.h" 23 23 #include "routing.h" 24 24 #include "send.h" 25 + #include "hash.h" 25 26 #include "soft-interface.h" 26 27 #include "hard-interface.h" 27 28 #include "device.h" 28 29 #include "translation-table.h" 30 + #include "originator.h" 29 31 #include "types.h" 30 - #include "hash.h" 31 32 #include "ring_buffer.h" 32 33 #include "vis.h" 33 34 #include "aggregation.h" 34 35 #include "compat.h" 35 36 36 37 DECLARE_WAIT_QUEUE_HEAD(thread_wait); 37 - static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); 38 38 39 39 static atomic_t data_ready_cond; 40 40 atomic_t exit_cond; 41 - 42 - static void start_purge_timer(void) 43 - { 44 - queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ); 45 - } 46 - 47 - int originator_init(void) 48 - { 49 - if (orig_hash) 50 - return 1; 51 - 52 - spin_lock(&orig_hash_lock); 53 - orig_hash = hash_new(128, compare_orig, choose_orig); 54 - 55 - if (!orig_hash) 56 - goto err; 57 - 58 - spin_unlock(&orig_hash_lock); 59 - start_purge_timer(); 60 - return 1; 61 - 62 - err: 63 - spin_unlock(&orig_hash_lock); 64 - return 0; 65 - } 66 - 67 - void originator_free(void) 68 - { 69 - if (!orig_hash) 70 - return; 71 - 72 - cancel_delayed_work_sync(&purge_orig_wq); 73 - 74 - spin_lock(&orig_hash_lock); 75 - hash_delete(orig_hash, free_orig_node); 76 - orig_hash = NULL; 77 - spin_unlock(&orig_hash_lock); 78 - } 79 - 80 - static struct neigh_node * 81 - create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, 82 - uint8_t *neigh, struct batman_if *if_incoming) 83 - { 84 - struct neigh_node *neigh_node; 85 - 86 - bat_dbg(DBG_BATMAN, "Creating new last-hop neighbour of originator\n"); 87 - 88 - neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC); 89 - memset(neigh_node, 0, sizeof(struct neigh_node)); 90 - INIT_LIST_HEAD(&neigh_node->list); 91 - 92 - memcpy(neigh_node->addr, neigh, ETH_ALEN); 93 - neigh_node->orig_node = orig_neigh_node; 94 - neigh_node->if_incoming = if_incoming; 95 - 96 - list_add_tail(&neigh_node->list, &orig_node->neigh_list); 97 - return neigh_node; 98 - } 99 - 100 - void free_orig_node(void *data) 101 - { 102 - struct list_head *list_pos, *list_pos_tmp; 103 - struct neigh_node *neigh_node; 104 - struct orig_node *orig_node = (struct orig_node *)data; 105 - 106 - /* for all neighbours towards this originator ... */ 107 - list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 108 - neigh_node = list_entry(list_pos, struct neigh_node, list); 109 - 110 - list_del(list_pos); 111 - kfree(neigh_node); 112 - } 113 - 114 - hna_global_del_orig(orig_node, "originator timed out"); 115 - 116 - kfree(orig_node->bcast_own); 117 - kfree(orig_node->bcast_own_sum); 118 - kfree(orig_node); 119 - } 120 - 121 - /* this function finds or creates an originator entry for the given 122 - * address if it does not exits */ 123 - static struct orig_node *get_orig_node(uint8_t *addr) 124 - { 125 - struct orig_node *orig_node; 126 - struct hashtable_t *swaphash; 127 - char orig_str[ETH_STR_LEN]; 128 - int size; 129 - 130 - orig_node = ((struct orig_node *)hash_find(orig_hash, addr)); 131 - 132 - if (orig_node != NULL) 133 - return orig_node; 134 - 135 - addr_to_string(orig_str, addr); 136 - bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str); 137 - 138 - orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC); 139 - memset(orig_node, 0, sizeof(struct orig_node)); 140 - INIT_LIST_HEAD(&orig_node->neigh_list); 141 - 142 - memcpy(orig_node->orig, addr, ETH_ALEN); 143 - orig_node->router = NULL; 144 - orig_node->batman_if = NULL; 145 - orig_node->hna_buff = NULL; 146 - 147 - size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS; 148 - 149 - orig_node->bcast_own = kmalloc(size, GFP_ATOMIC); 150 - memset(orig_node->bcast_own, 0, size); 151 - 152 - size = num_ifs * sizeof(uint8_t); 153 - orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC); 154 - memset(orig_node->bcast_own_sum, 0, size); 155 - 156 - hash_add(orig_hash, orig_node); 157 - 158 - if (orig_hash->elements * 4 > orig_hash->size) { 159 - swaphash = hash_resize(orig_hash, orig_hash->size * 2); 160 - 161 - if (swaphash == NULL) 162 - printk(KERN_ERR 163 - "batman-adv:Couldn't resize orig hash table \n"); 164 - else 165 - orig_hash = swaphash; 166 - } 167 - 168 - return orig_node; 169 - } 170 - 171 41 void slide_own_bcast_window(struct batman_if *batman_if) 172 42 { 173 43 struct hash_it_t *hashit = NULL; ··· 116 246 } 117 247 118 248 119 - static void update_routes(struct orig_node *orig_node, 249 + void update_routes(struct orig_node *orig_node, 120 250 struct neigh_node *neigh_node, 121 251 unsigned char *hna_buff, int hna_buff_len) 122 252 { ··· 549 679 0, hna_buff_len, if_incoming); 550 680 } 551 681 552 - static bool purge_orig_neigbours(struct orig_node *orig_node, 553 - struct neigh_node **best_neigh_node) 554 - { 555 - struct list_head *list_pos, *list_pos_tmp; 556 - char neigh_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; 557 - struct neigh_node *neigh_node; 558 - bool neigh_purged = false; 559 - 560 - *best_neigh_node = NULL; 561 - 562 - 563 - /* for all neighbours towards this originator ... */ 564 - list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 565 - neigh_node = list_entry(list_pos, struct neigh_node, list); 566 - 567 - if (time_after(jiffies, 568 - (neigh_node->last_valid + 569 - ((PURGE_TIMEOUT * HZ) / 1000)))) { 570 - 571 - addr_to_string(neigh_str, neigh_node->addr); 572 - bat_dbg(DBG_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ)); 573 - 574 - neigh_purged = true; 575 - list_del(list_pos); 576 - kfree(neigh_node); 577 - } else { 578 - if ((*best_neigh_node == NULL) || 579 - (neigh_node->tq_avg > (*best_neigh_node)->tq_avg)) 580 - *best_neigh_node = neigh_node; 581 - } 582 - } 583 - return neigh_purged; 584 - } 585 - 586 - static bool purge_orig_node(struct orig_node *orig_node) 587 - { 588 - struct neigh_node *best_neigh_node; 589 - char orig_str[ETH_STR_LEN]; 590 - 591 - addr_to_string(orig_str, orig_node->orig); 592 - 593 - if (time_after(jiffies, 594 - (orig_node->last_valid + 595 - ((2 * PURGE_TIMEOUT * HZ) / 1000)))) { 596 - 597 - bat_dbg(DBG_BATMAN, 598 - "Originator timeout: originator %s, last_valid %lu\n", 599 - orig_str, (orig_node->last_valid / HZ)); 600 - return true; 601 - } else { 602 - if (purge_orig_neigbours(orig_node, &best_neigh_node)) 603 - update_routes(orig_node, best_neigh_node, 604 - orig_node->hna_buff, 605 - orig_node->hna_buff_len); 606 - } 607 - return false; 608 - } 609 - 610 - 611 - void purge_orig(struct work_struct *work) 612 - { 613 - struct hash_it_t *hashit = NULL; 614 - struct orig_node *orig_node; 615 - 616 - spin_lock(&orig_hash_lock); 617 - 618 - /* for all origins... */ 619 - while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { 620 - orig_node = hashit->bucket->data; 621 - if (purge_orig_node(orig_node)) { 622 - hash_remove_bucket(orig_hash, hashit); 623 - free_orig_node(orig_node); 624 - } 625 - } 626 - 627 - spin_unlock(&orig_hash_lock); 628 - 629 - start_purge_timer(); 630 - } 631 682 632 683 static int receive_raw_packet(struct socket *raw_sock, 633 684 unsigned char *packet_buff, int packet_buff_len) ··· 969 1178 int result = -EAGAIN; 970 1179 971 1180 if (batman_if->raw_sock) { 972 - result = receive_raw_packet(batman_if->raw_sock, 973 - packet_buff, 974 - PACKBUFF_SIZE); 1181 + result = receive_raw_packet(batman_if->raw_sock, 1182 + packet_buff, 1183 + PACKBUFF_SIZE); 975 1184 } 976 1185 return result; 977 1186 }
+7 -5
drivers/staging/batman-adv/routing.h
··· 24 24 extern wait_queue_head_t thread_wait; 25 25 extern atomic_t exit_cond; 26 26 27 - int originator_init(void); 28 - void free_orig_node(void *data); 29 - void originator_free(void); 30 27 void slide_own_bcast_window(struct batman_if *batman_if); 31 28 void batman_data_ready(struct sock *sk, int len); 32 - void purge_orig(struct work_struct *work); 33 29 int packet_recv_thread(void *data); 34 - void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming); 30 + void receive_bat_packet(struct ethhdr *ethhdr, 31 + struct batman_packet *batman_packet, 32 + unsigned char *hna_buff, int hna_buff_len, 33 + struct batman_if *if_incoming); 34 + void update_routes(struct orig_node *orig_node, 35 + struct neigh_node *neigh_node, 36 + unsigned char *hna_buff, int hna_buff_len);