1/* 2 * Copyright (C) 2009-2010 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#include "hard-interface.h" 30 31static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); 32 33static void start_purge_timer(void) 34{ 35 queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ); 36} 37 38int originator_init(void) 39{ 40 unsigned long flags; 41 if (orig_hash) 42 return 1; 43 44 spin_lock_irqsave(&orig_hash_lock, flags); 45 orig_hash = hash_new(128, compare_orig, choose_orig); 46 47 if (!orig_hash) 48 goto err; 49 50 spin_unlock_irqrestore(&orig_hash_lock, flags); 51 start_purge_timer(); 52 return 1; 53 54err: 55 spin_unlock_irqrestore(&orig_hash_lock, flags); 56 return 0; 57} 58 59struct neigh_node * 60create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, 61 uint8_t *neigh, struct batman_if *if_incoming) 62{ 63 struct bat_priv *bat_priv = netdev_priv(soft_device); 64 struct neigh_node *neigh_node; 65 66 bat_dbg(DBG_BATMAN, bat_priv, 67 "Creating new last-hop neighbor of originator\n"); 68 69 neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC); 70 if (!neigh_node) 71 return NULL; 72 73 INIT_LIST_HEAD(&neigh_node->list); 74 75 memcpy(neigh_node->addr, neigh, ETH_ALEN); 76 neigh_node->orig_node = orig_neigh_node; 77 neigh_node->if_incoming = if_incoming; 78 79 list_add_tail(&neigh_node->list, &orig_node->neigh_list); 80 return neigh_node; 81} 82 83static void free_orig_node(void *data) 84{ 85 struct list_head *list_pos, *list_pos_tmp; 86 struct neigh_node *neigh_node; 87 struct orig_node *orig_node = (struct orig_node *)data; 88 89 /* for all neighbors towards this originator ... */ 90 list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 91 neigh_node = list_entry(list_pos, struct neigh_node, list); 92 93 list_del(list_pos); 94 kfree(neigh_node); 95 } 96 97 hna_global_del_orig(orig_node, "originator timed out"); 98 99 kfree(orig_node->bcast_own); 100 kfree(orig_node->bcast_own_sum); 101 kfree(orig_node); 102} 103 104void originator_free(void) 105{ 106 unsigned long flags; 107 108 if (!orig_hash) 109 return; 110 111 cancel_delayed_work_sync(&purge_orig_wq); 112 113 spin_lock_irqsave(&orig_hash_lock, flags); 114 hash_delete(orig_hash, free_orig_node); 115 orig_hash = NULL; 116 spin_unlock_irqrestore(&orig_hash_lock, flags); 117} 118 119/* this function finds or creates an originator entry for the given 120 * address if it does not exits */ 121struct orig_node *get_orig_node(uint8_t *addr) 122{ 123 struct bat_priv *bat_priv = netdev_priv(soft_device); 124 struct orig_node *orig_node; 125 struct hashtable_t *swaphash; 126 int size; 127 128 orig_node = ((struct orig_node *)hash_find(orig_hash, addr)); 129 130 if (orig_node != NULL) 131 return orig_node; 132 133 bat_dbg(DBG_BATMAN, bat_priv, 134 "Creating new originator: %pM\n", addr); 135 136 orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC); 137 if (!orig_node) 138 return NULL; 139 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->hna_buff = NULL; 145 orig_node->bcast_seqno_reset = jiffies - 1 146 - msecs_to_jiffies(RESET_PROTECTION_MS); 147 orig_node->batman_seqno_reset = jiffies - 1 148 - msecs_to_jiffies(RESET_PROTECTION_MS); 149 150 size = bat_priv->num_ifaces * sizeof(TYPE_OF_WORD) * NUM_WORDS; 151 152 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC); 153 if (!orig_node->bcast_own) 154 goto free_orig_node; 155 156 size = bat_priv->num_ifaces * sizeof(uint8_t); 157 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); 158 if (!orig_node->bcast_own_sum) 159 goto free_bcast_own; 160 161 if (hash_add(orig_hash, orig_node) < 0) 162 goto free_bcast_own_sum; 163 164 if (orig_hash->elements * 4 > orig_hash->size) { 165 swaphash = hash_resize(orig_hash, orig_hash->size * 2); 166 167 if (swaphash == NULL) 168 bat_err(soft_device, 169 "Couldn't resize orig hash table\n"); 170 else 171 orig_hash = swaphash; 172 } 173 174 return orig_node; 175free_bcast_own_sum: 176 kfree(orig_node->bcast_own_sum); 177free_bcast_own: 178 kfree(orig_node->bcast_own); 179free_orig_node: 180 kfree(orig_node); 181 return NULL; 182} 183 184static bool purge_orig_neighbors(struct orig_node *orig_node, 185 struct neigh_node **best_neigh_node) 186{ 187 struct bat_priv *bat_priv = netdev_priv(soft_device); 188 struct list_head *list_pos, *list_pos_tmp; 189 struct neigh_node *neigh_node; 190 bool neigh_purged = false; 191 192 *best_neigh_node = NULL; 193 194 /* for all neighbors towards this originator ... */ 195 list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { 196 neigh_node = list_entry(list_pos, struct neigh_node, list); 197 198 if ((time_after(jiffies, 199 neigh_node->last_valid + PURGE_TIMEOUT * HZ)) || 200 (neigh_node->if_incoming->if_status == 201 IF_TO_BE_REMOVED)) { 202 203 if (neigh_node->if_incoming->if_status == 204 IF_TO_BE_REMOVED) 205 bat_dbg(DBG_BATMAN, bat_priv, 206 "neighbor purge: originator %pM, " 207 "neighbor: %pM, iface: %s\n", 208 orig_node->orig, neigh_node->addr, 209 neigh_node->if_incoming->dev); 210 else 211 bat_dbg(DBG_BATMAN, bat_priv, 212 "neighbor timeout: originator %pM, " 213 "neighbor: %pM, last_valid: %lu\n", 214 orig_node->orig, neigh_node->addr, 215 (neigh_node->last_valid / HZ)); 216 217 neigh_purged = true; 218 list_del(list_pos); 219 kfree(neigh_node); 220 } else { 221 if ((*best_neigh_node == NULL) || 222 (neigh_node->tq_avg > (*best_neigh_node)->tq_avg)) 223 *best_neigh_node = neigh_node; 224 } 225 } 226 return neigh_purged; 227} 228 229static bool purge_orig_node(struct orig_node *orig_node) 230{ 231 struct bat_priv *bat_priv = netdev_priv(soft_device); 232 struct neigh_node *best_neigh_node; 233 234 if (time_after(jiffies, 235 orig_node->last_valid + 2 * PURGE_TIMEOUT * HZ)) { 236 237 bat_dbg(DBG_BATMAN, bat_priv, 238 "Originator timeout: originator %pM, last_valid %lu\n", 239 orig_node->orig, (orig_node->last_valid / HZ)); 240 return true; 241 } else { 242 if (purge_orig_neighbors(orig_node, &best_neigh_node)) { 243 update_routes(orig_node, best_neigh_node, 244 orig_node->hna_buff, 245 orig_node->hna_buff_len); 246 /* update bonding candidates, we could have lost 247 * some candidates. */ 248 update_bonding_candidates(bat_priv, orig_node); 249 } 250 } 251 252 return false; 253} 254 255void purge_orig(struct work_struct *work) 256{ 257 HASHIT(hashit); 258 struct orig_node *orig_node; 259 unsigned long flags; 260 261 spin_lock_irqsave(&orig_hash_lock, flags); 262 263 /* for all origins... */ 264 while (hash_iterate(orig_hash, &hashit)) { 265 orig_node = hashit.bucket->data; 266 if (purge_orig_node(orig_node)) { 267 hash_remove_bucket(orig_hash, &hashit); 268 free_orig_node(orig_node); 269 } 270 } 271 272 spin_unlock_irqrestore(&orig_hash_lock, flags); 273 274 /* if work == NULL we were not called by the timer 275 * and thus do not need to re-arm the timer */ 276 if (work) 277 start_purge_timer(); 278} 279 280int orig_seq_print_text(struct seq_file *seq, void *offset) 281{ 282 HASHIT(hashit); 283 struct net_device *net_dev = (struct net_device *)seq->private; 284 struct bat_priv *bat_priv = netdev_priv(net_dev); 285 struct orig_node *orig_node; 286 struct neigh_node *neigh_node; 287 int batman_count = 0; 288 int last_seen_secs; 289 int last_seen_msecs; 290 unsigned long flags; 291 char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; 292 293 if ((!bat_priv->primary_if) || 294 (bat_priv->primary_if->if_status != IF_ACTIVE)) { 295 if (!bat_priv->primary_if) 296 return seq_printf(seq, "BATMAN mesh %s disabled - " 297 "please specify interfaces to enable it\n", 298 net_dev->name); 299 300 return seq_printf(seq, "BATMAN mesh %s " 301 "disabled - primary interface not active\n", 302 net_dev->name); 303 } 304 305 rcu_read_lock(); 306 seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", 307 SOURCE_VERSION, REVISION_VERSION_STR, 308 bat_priv->primary_if->dev, bat_priv->primary_if->addr_str, 309 net_dev->name); 310 seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", 311 "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", 312 "outgoingIF", "Potential nexthops"); 313 rcu_read_unlock(); 314 315 spin_lock_irqsave(&orig_hash_lock, flags); 316 317 while (hash_iterate(orig_hash, &hashit)) { 318 319 orig_node = hashit.bucket->data; 320 321 if (!orig_node->router) 322 continue; 323 324 if (orig_node->router->tq_avg == 0) 325 continue; 326 327 addr_to_string(orig_str, orig_node->orig); 328 addr_to_string(router_str, orig_node->router->addr); 329 last_seen_secs = jiffies_to_msecs(jiffies - 330 orig_node->last_valid) / 1000; 331 last_seen_msecs = jiffies_to_msecs(jiffies - 332 orig_node->last_valid) % 1000; 333 334 seq_printf(seq, "%-17s %4i.%03is (%3i) %17s [%10s]:", 335 orig_str, last_seen_secs, last_seen_msecs, 336 orig_node->router->tq_avg, router_str, 337 orig_node->router->if_incoming->dev); 338 339 list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { 340 addr_to_string(orig_str, neigh_node->addr); 341 seq_printf(seq, " %17s (%3i)", orig_str, 342 neigh_node->tq_avg); 343 } 344 345 seq_printf(seq, "\n"); 346 batman_count++; 347 } 348 349 spin_unlock_irqrestore(&orig_hash_lock, flags); 350 351 if ((batman_count == 0)) 352 seq_printf(seq, "No batman nodes in range ...\n"); 353 354 return 0; 355} 356 357static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) 358{ 359 void *data_ptr; 360 361 data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS, 362 GFP_ATOMIC); 363 if (!data_ptr) { 364 pr_err("Can't resize orig: out of memory\n"); 365 return -1; 366 } 367 368 memcpy(data_ptr, orig_node->bcast_own, 369 (max_if_num - 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS); 370 kfree(orig_node->bcast_own); 371 orig_node->bcast_own = data_ptr; 372 373 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); 374 if (!data_ptr) { 375 pr_err("Can't resize orig: out of memory\n"); 376 return -1; 377 } 378 379 memcpy(data_ptr, orig_node->bcast_own_sum, 380 (max_if_num - 1) * sizeof(uint8_t)); 381 kfree(orig_node->bcast_own_sum); 382 orig_node->bcast_own_sum = data_ptr; 383 384 return 0; 385} 386 387int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) 388{ 389 struct orig_node *orig_node; 390 unsigned long flags; 391 HASHIT(hashit); 392 393 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on 394 * if_num */ 395 spin_lock_irqsave(&orig_hash_lock, flags); 396 397 while (hash_iterate(orig_hash, &hashit)) { 398 orig_node = hashit.bucket->data; 399 400 if (orig_node_add_if(orig_node, max_if_num) == -1) 401 goto err; 402 } 403 404 spin_unlock_irqrestore(&orig_hash_lock, flags); 405 return 0; 406 407err: 408 spin_unlock_irqrestore(&orig_hash_lock, flags); 409 return -ENOMEM; 410} 411 412static int orig_node_del_if(struct orig_node *orig_node, 413 int max_if_num, int del_if_num) 414{ 415 void *data_ptr = NULL; 416 int chunk_size; 417 418 /* last interface was removed */ 419 if (max_if_num == 0) 420 goto free_bcast_own; 421 422 chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS; 423 data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC); 424 if (!data_ptr) { 425 pr_err("Can't resize orig: out of memory\n"); 426 return -1; 427 } 428 429 /* copy first part */ 430 memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size); 431 432 /* copy second part */ 433 memcpy(data_ptr, 434 orig_node->bcast_own + ((del_if_num + 1) * chunk_size), 435 (max_if_num - del_if_num) * chunk_size); 436 437free_bcast_own: 438 kfree(orig_node->bcast_own); 439 orig_node->bcast_own = data_ptr; 440 441 if (max_if_num == 0) 442 goto free_own_sum; 443 444 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); 445 if (!data_ptr) { 446 pr_err("Can't resize orig: out of memory\n"); 447 return -1; 448 } 449 450 memcpy(data_ptr, orig_node->bcast_own_sum, 451 del_if_num * sizeof(uint8_t)); 452 453 memcpy(data_ptr, 454 orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)), 455 (max_if_num - del_if_num) * sizeof(uint8_t)); 456 457free_own_sum: 458 kfree(orig_node->bcast_own_sum); 459 orig_node->bcast_own_sum = data_ptr; 460 461 return 0; 462} 463 464int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) 465{ 466 struct batman_if *batman_if_tmp; 467 struct orig_node *orig_node; 468 unsigned long flags; 469 HASHIT(hashit); 470 int ret; 471 472 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on 473 * if_num */ 474 spin_lock_irqsave(&orig_hash_lock, flags); 475 476 while (hash_iterate(orig_hash, &hashit)) { 477 orig_node = hashit.bucket->data; 478 479 ret = orig_node_del_if(orig_node, max_if_num, 480 batman_if->if_num); 481 482 if (ret == -1) 483 goto err; 484 } 485 486 /* renumber remaining batman interfaces _inside_ of orig_hash_lock */ 487 rcu_read_lock(); 488 list_for_each_entry_rcu(batman_if_tmp, &if_list, list) { 489 if (batman_if_tmp->if_status == IF_NOT_IN_USE) 490 continue; 491 492 if (batman_if == batman_if_tmp) 493 continue; 494 495 if (batman_if_tmp->if_num > batman_if->if_num) 496 batman_if_tmp->if_num--; 497 } 498 rcu_read_unlock(); 499 500 batman_if->if_num = -1; 501 spin_unlock_irqrestore(&orig_hash_lock, flags); 502 return 0; 503 504err: 505 spin_unlock_irqrestore(&orig_hash_lock, flags); 506 return -ENOMEM; 507} 508