Staging: batman-adv: Split originator handling parts out of routing.c
authorAndrew Lunn <andrew@lunn.ch>
Sat, 12 Dec 2009 22:39:45 +0000 (23:39 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 4 Mar 2010 00:42:30 +0000 (16:42 -0800)
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>
drivers/staging/batman-adv/Makefile
drivers/staging/batman-adv/main.c
drivers/staging/batman-adv/originator.c [new file with mode: 0644]
drivers/staging/batman-adv/originator.h [new file with mode: 0644]
drivers/staging/batman-adv/routing.c
drivers/staging/batman-adv/routing.h

index 64bdb78..42b4e63 100644 (file)
@@ -19,4 +19,4 @@
 #
 
 obj-m += batman-adv.o
-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
+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
index 4b93a5d..a74bfbe 100644 (file)
@@ -23,6 +23,7 @@
 #include "proc.h"
 #include "routing.h"
 #include "send.h"
+#include "originator.h"
 #include "soft-interface.h"
 #include "device.h"
 #include "translation-table.h"
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c
new file mode 100644 (file)
index 0000000..9962af7
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/* increase the reference counter for this originator */
+
+#include "main.h"
+#include "originator.h"
+#include "hash.h"
+#include "translation-table.h"
+#include "routing.h"
+
+
+static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
+
+static void start_purge_timer(void)
+{
+       queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
+}
+
+int originator_init(void)
+{
+       if (orig_hash)
+               return 1;
+
+       spin_lock(&orig_hash_lock);
+       orig_hash = hash_new(128, compare_orig, choose_orig);
+
+       if (!orig_hash)
+               goto err;
+
+       spin_unlock(&orig_hash_lock);
+       start_purge_timer();
+       return 1;
+
+err:
+       spin_unlock(&orig_hash_lock);
+       return 0;
+}
+
+void originator_free(void)
+{
+       if (!orig_hash)
+               return;
+
+       cancel_delayed_work_sync(&purge_orig_wq);
+
+       spin_lock(&orig_hash_lock);
+       hash_delete(orig_hash, free_orig_node);
+       orig_hash = NULL;
+       spin_unlock(&orig_hash_lock);
+}
+
+struct neigh_node *
+create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
+               uint8_t *neigh, struct batman_if *if_incoming)
+{
+       struct neigh_node *neigh_node;
+
+       bat_dbg(DBG_BATMAN, "Creating new last-hop neighbour of originator\n");
+
+       neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
+       memset(neigh_node, 0, sizeof(struct neigh_node));
+       INIT_LIST_HEAD(&neigh_node->list);
+
+       memcpy(neigh_node->addr, neigh, ETH_ALEN);
+       neigh_node->orig_node = orig_neigh_node;
+       neigh_node->if_incoming = if_incoming;
+
+       list_add_tail(&neigh_node->list, &orig_node->neigh_list);
+       return neigh_node;
+}
+
+void free_orig_node(void *data)
+{
+       struct list_head *list_pos, *list_pos_tmp;
+       struct neigh_node *neigh_node;
+       struct orig_node *orig_node = (struct orig_node *)data;
+
+       /* for all neighbours towards this originator ... */
+       list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+               neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+               list_del(list_pos);
+               kfree(neigh_node);
+       }
+
+       hna_global_del_orig(orig_node, "originator timed out");
+
+       kfree(orig_node->bcast_own);
+       kfree(orig_node->bcast_own_sum);
+       kfree(orig_node);
+}
+
+/* this function finds or creates an originator entry for the given
+ * address if it does not exits */
+struct orig_node *get_orig_node(uint8_t *addr)
+{
+       struct orig_node *orig_node;
+       struct hashtable_t *swaphash;
+       char orig_str[ETH_STR_LEN];
+       int size;
+
+       orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
+
+       if (orig_node != NULL)
+               return orig_node;
+
+       addr_to_string(orig_str, addr);
+       bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str);
+
+       orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
+       memset(orig_node, 0, sizeof(struct orig_node));
+       INIT_LIST_HEAD(&orig_node->neigh_list);
+
+       memcpy(orig_node->orig, addr, ETH_ALEN);
+       orig_node->router = NULL;
+       orig_node->batman_if = NULL;
+       orig_node->hna_buff = NULL;
+
+       size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
+
+       orig_node->bcast_own = kmalloc(size, GFP_ATOMIC);
+       memset(orig_node->bcast_own, 0, size);
+
+       size = num_ifs * sizeof(uint8_t);
+       orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC);
+       memset(orig_node->bcast_own_sum, 0, size);
+
+       hash_add(orig_hash, orig_node);
+
+       if (orig_hash->elements * 4 > orig_hash->size) {
+               swaphash = hash_resize(orig_hash, orig_hash->size * 2);
+
+               if (swaphash == NULL)
+                       printk(KERN_ERR
+                              "batman-adv:Couldn't resize orig hash table \n");
+               else
+                       orig_hash = swaphash;
+       }
+
+       return orig_node;
+}
+
+static bool purge_orig_neigbours(struct orig_node *orig_node,
+                                struct neigh_node **best_neigh_node)
+{
+       struct list_head *list_pos, *list_pos_tmp;
+       char neigh_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
+       struct neigh_node *neigh_node;
+       bool neigh_purged = false;
+
+       *best_neigh_node = NULL;
+
+
+       /* for all neighbours towards this originator ... */
+       list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+               neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+               if (time_after(jiffies,
+                              (neigh_node->last_valid +
+                               ((PURGE_TIMEOUT * HZ) / 1000)))) {
+
+                       addr_to_string(neigh_str, neigh_node->addr);
+                       addr_to_string(orig_str, orig_node->orig);
+                       bat_dbg(DBG_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
+
+                       neigh_purged = true;
+                       list_del(list_pos);
+                       kfree(neigh_node);
+               } else {
+                       if ((*best_neigh_node == NULL) ||
+                           (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
+                               *best_neigh_node = neigh_node;
+               }
+       }
+       return neigh_purged;
+}
+
+
+static bool purge_orig_node(struct orig_node *orig_node)
+{
+       struct neigh_node *best_neigh_node;
+       char orig_str[ETH_STR_LEN];
+
+       addr_to_string(orig_str, orig_node->orig);
+
+       if (time_after(jiffies,
+                      (orig_node->last_valid +
+                       ((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
+
+               bat_dbg(DBG_BATMAN,
+                       "Originator timeout: originator %s, last_valid %lu\n",
+                       orig_str, (orig_node->last_valid / HZ));
+               return true;
+       } else {
+               if (purge_orig_neigbours(orig_node, &best_neigh_node))
+                       update_routes(orig_node, best_neigh_node,
+                                     orig_node->hna_buff,
+                                     orig_node->hna_buff_len);
+       }
+       return false;
+}
+
+void purge_orig(struct work_struct *work)
+{
+       struct hash_it_t *hashit = NULL;
+       struct orig_node *orig_node;
+
+       spin_lock(&orig_hash_lock);
+
+       /* for all origins... */
+       while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+               orig_node = hashit->bucket->data;
+               if (purge_orig_node(orig_node)) {
+                       hash_remove_bucket(orig_hash, hashit);
+                       free_orig_node(orig_node);
+               }
+       }
+
+       spin_unlock(&orig_hash_lock);
+
+       start_purge_timer();
+}
+
+
diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h
new file mode 100644 (file)
index 0000000..6ef7a05
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+int originator_init(void);
+void free_orig_node(void *data);
+void originator_free(void);
+void purge_orig(struct work_struct *work);
+struct orig_node *orig_find(char *mac);
+struct orig_node *get_orig_node(uint8_t *addr);
+struct neigh_node *
+create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
+               uint8_t *neigh, struct batman_if *if_incoming);
+
index 6a8d73d..e8d7127 100644 (file)
 #include "main.h"
 #include "routing.h"
 #include "send.h"
+#include "hash.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
 #include "device.h"
 #include "translation-table.h"
+#include "originator.h"
 #include "types.h"
-#include "hash.h"
 #include "ring_buffer.h"
 #include "vis.h"
 #include "aggregation.h"
 #include "compat.h"
 
 DECLARE_WAIT_QUEUE_HEAD(thread_wait);
-static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
 
 static atomic_t data_ready_cond;
 atomic_t exit_cond;
-
-static void start_purge_timer(void)
-{
-       queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
-}
-
-int originator_init(void)
-{
-       if (orig_hash)
-               return 1;
-
-       spin_lock(&orig_hash_lock);
-       orig_hash = hash_new(128, compare_orig, choose_orig);
-
-       if (!orig_hash)
-               goto err;
-
-       spin_unlock(&orig_hash_lock);
-       start_purge_timer();
-       return 1;
-
-err:
-       spin_unlock(&orig_hash_lock);
-       return 0;
-}
-
-void originator_free(void)
-{
-       if (!orig_hash)
-               return;
-
-       cancel_delayed_work_sync(&purge_orig_wq);
-
-       spin_lock(&orig_hash_lock);
-       hash_delete(orig_hash, free_orig_node);
-       orig_hash = NULL;
-       spin_unlock(&orig_hash_lock);
-}
-
-static struct neigh_node *
-create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
-               uint8_t *neigh, struct batman_if *if_incoming)
-{
-       struct neigh_node *neigh_node;
-
-       bat_dbg(DBG_BATMAN, "Creating new last-hop neighbour of originator\n");
-
-       neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
-       memset(neigh_node, 0, sizeof(struct neigh_node));
-       INIT_LIST_HEAD(&neigh_node->list);
-
-       memcpy(neigh_node->addr, neigh, ETH_ALEN);
-       neigh_node->orig_node = orig_neigh_node;
-       neigh_node->if_incoming = if_incoming;
-
-       list_add_tail(&neigh_node->list, &orig_node->neigh_list);
-       return neigh_node;
-}
-
-void free_orig_node(void *data)
-{
-       struct list_head *list_pos, *list_pos_tmp;
-       struct neigh_node *neigh_node;
-       struct orig_node *orig_node = (struct orig_node *)data;
-
-       /* for all neighbours towards this originator ... */
-       list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
-               neigh_node = list_entry(list_pos, struct neigh_node, list);
-
-               list_del(list_pos);
-               kfree(neigh_node);
-       }
-
-       hna_global_del_orig(orig_node, "originator timed out");
-
-       kfree(orig_node->bcast_own);
-       kfree(orig_node->bcast_own_sum);
-       kfree(orig_node);
-}
-
-/* this function finds or creates an originator entry for the given
- * address if it does not exits */
-static struct orig_node *get_orig_node(uint8_t *addr)
-{
-       struct orig_node *orig_node;
-       struct hashtable_t *swaphash;
-       char orig_str[ETH_STR_LEN];
-       int size;
-
-       orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
-
-       if (orig_node != NULL)
-               return orig_node;
-
-       addr_to_string(orig_str, addr);
-       bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str);
-
-       orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
-       memset(orig_node, 0, sizeof(struct orig_node));
-       INIT_LIST_HEAD(&orig_node->neigh_list);
-
-       memcpy(orig_node->orig, addr, ETH_ALEN);
-       orig_node->router = NULL;
-       orig_node->batman_if = NULL;
-       orig_node->hna_buff = NULL;
-
-       size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
-
-       orig_node->bcast_own = kmalloc(size, GFP_ATOMIC);
-       memset(orig_node->bcast_own, 0, size);
-
-       size = num_ifs * sizeof(uint8_t);
-       orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC);
-       memset(orig_node->bcast_own_sum, 0, size);
-
-       hash_add(orig_hash, orig_node);
-
-       if (orig_hash->elements * 4 > orig_hash->size) {
-               swaphash = hash_resize(orig_hash, orig_hash->size * 2);
-
-               if (swaphash == NULL)
-                       printk(KERN_ERR
-                              "batman-adv:Couldn't resize orig hash table \n");
-               else
-                       orig_hash = swaphash;
-       }
-
-       return orig_node;
-}
-
 void slide_own_bcast_window(struct batman_if *batman_if)
 {
        struct hash_it_t *hashit = NULL;
@@ -246,7 +116,7 @@ static void update_route(struct orig_node *orig_node,
 }
 
 
-static void update_routes(struct orig_node *orig_node,
+void update_routes(struct orig_node *orig_node,
                          struct neigh_node *neigh_node,
                          unsigned char *hna_buff, int hna_buff_len)
 {
@@ -679,85 +549,6 @@ void receive_bat_packet(struct ethhdr *ethhdr,
                                0, hna_buff_len, if_incoming);
 }
 
-static bool purge_orig_neigbours(struct orig_node *orig_node,
-                                struct neigh_node **best_neigh_node)
-{
-       struct list_head *list_pos, *list_pos_tmp;
-       char neigh_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
-       struct neigh_node *neigh_node;
-       bool neigh_purged = false;
-
-       *best_neigh_node = NULL;
-
-
-       /* for all neighbours towards this originator ... */
-       list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
-               neigh_node = list_entry(list_pos, struct neigh_node, list);
-
-               if (time_after(jiffies,
-                              (neigh_node->last_valid +
-                               ((PURGE_TIMEOUT * HZ) / 1000)))) {
-
-                       addr_to_string(neigh_str, neigh_node->addr);
-                       bat_dbg(DBG_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
-
-                       neigh_purged = true;
-                       list_del(list_pos);
-                       kfree(neigh_node);
-               } else {
-                       if ((*best_neigh_node == NULL) ||
-                           (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
-                               *best_neigh_node = neigh_node;
-               }
-       }
-       return neigh_purged;
-}
-
-static bool purge_orig_node(struct orig_node *orig_node)
-{
-       struct neigh_node *best_neigh_node;
-       char orig_str[ETH_STR_LEN];
-
-       addr_to_string(orig_str, orig_node->orig);
-
-       if (time_after(jiffies,
-                      (orig_node->last_valid +
-                       ((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
-
-               bat_dbg(DBG_BATMAN,
-                       "Originator timeout: originator %s, last_valid %lu\n",
-                       orig_str, (orig_node->last_valid / HZ));
-               return true;
-       } else {
-               if (purge_orig_neigbours(orig_node, &best_neigh_node))
-                       update_routes(orig_node, best_neigh_node,
-                                     orig_node->hna_buff,
-                                     orig_node->hna_buff_len);
-       }
-       return false;
-}
-
-
-void purge_orig(struct work_struct *work)
-{
-       struct hash_it_t *hashit = NULL;
-       struct orig_node *orig_node;
-
-       spin_lock(&orig_hash_lock);
-
-       /* for all origins... */
-       while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-               orig_node = hashit->bucket->data;
-               if (purge_orig_node(orig_node)) {
-                       hash_remove_bucket(orig_hash, hashit);
-                       free_orig_node(orig_node);
-               }
-       }
-
-       spin_unlock(&orig_hash_lock);
-
-       start_purge_timer();
-}
 
 static int receive_raw_packet(struct socket *raw_sock,
                              unsigned char *packet_buff, int packet_buff_len)
@@ -1178,9 +969,9 @@ static int discard_one_packet(struct batman_if *batman_if,
        int result = -EAGAIN;
 
        if (batman_if->raw_sock) {
-                       result = receive_raw_packet(batman_if->raw_sock,
-                                                   packet_buff,
-                                                   PACKBUFF_SIZE);
+               result = receive_raw_packet(batman_if->raw_sock,
+                                           packet_buff,
+                                           PACKBUFF_SIZE);
        }
        return result;
 }
index 0123ea8..890a4f5 100644 (file)
 extern wait_queue_head_t thread_wait;
 extern atomic_t exit_cond;
 
-int originator_init(void);
-void free_orig_node(void *data);
-void originator_free(void);
 void slide_own_bcast_window(struct batman_if *batman_if);
 void batman_data_ready(struct sock *sk, int len);
-void purge_orig(struct work_struct *work);
 int packet_recv_thread(void *data);
-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);
+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);
+void update_routes(struct orig_node *orig_node,
+                               struct neigh_node *neigh_node,
+                               unsigned char *hna_buff, int hna_buff_len);