]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/staging/batman-adv/originator.c
Staging: batman-adv: Fix whitespace problems criticized by checkpatch.pl
[net-next-2.6.git] / drivers / staging / batman-adv / originator.c
index 2ce134995464e665394a3cf397e52e8e1cc4df77..25a9e215e1a0c47934d2da249f2a5cf7827fd189 100644 (file)
@@ -26,6 +26,7 @@
 #include "hash.h"
 #include "translation-table.h"
 #include "routing.h"
+#include "hard-interface.h"
 
 static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
 
@@ -117,6 +118,8 @@ void free_orig_node(void *data)
  * address if it does not exits */
 struct orig_node *get_orig_node(uint8_t *addr)
 {
+       /* FIXME: each batman_if will be attached to a softif */
+       struct bat_priv *bat_priv = netdev_priv(soft_device);
        struct orig_node *orig_node;
        struct hashtable_t *swaphash;
        int size;
@@ -126,7 +129,7 @@ struct orig_node *get_orig_node(uint8_t *addr)
        if (orig_node != NULL)
                return orig_node;
 
-       bat_dbg(DBG_BATMAN, "Creating new originator: %pM \n", addr);
+       bat_dbg(DBG_BATMAN, "Creating new originator: %pM\n", addr);
 
        orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
        if (!orig_node)
@@ -136,16 +139,17 @@ struct orig_node *get_orig_node(uint8_t *addr)
 
        memcpy(orig_node->orig, addr, ETH_ALEN);
        orig_node->router = NULL;
-       orig_node->batman_if = NULL;
        orig_node->hna_buff = NULL;
+       orig_node->bcast_seqno_reset = jiffies - msecs_to_jiffies(RESET_PROTECTION_MS) - 1;
+       orig_node->batman_seqno_reset = jiffies - msecs_to_jiffies(RESET_PROTECTION_MS) - 1;
 
-       size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
+       size = bat_priv->num_ifaces * sizeof(TYPE_OF_WORD) * NUM_WORDS;
 
        orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
        if (!orig_node->bcast_own)
                goto free_orig_node;
 
-       size = num_ifs * sizeof(uint8_t);
+       size = bat_priv->num_ifaces * sizeof(uint8_t);
        orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
        if (!orig_node->bcast_own_sum)
                goto free_bcast_own;
@@ -158,7 +162,7 @@ struct orig_node *get_orig_node(uint8_t *addr)
 
                if (swaphash == NULL)
                        printk(KERN_ERR
-                              "batman-adv:Couldn't resize orig hash table \n");
+                              "batman-adv:Couldn't resize orig hash table\n");
                else
                        orig_hash = swaphash;
        }
@@ -182,16 +186,25 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
 
        *best_neigh_node = NULL;
 
-
        /* for all neighbors 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,
+               if ((time_after(jiffies,
                               (neigh_node->last_valid +
-                               ((PURGE_TIMEOUT * HZ) / 1000)))) {
-
-                       bat_dbg(DBG_BATMAN, "neighbor timeout: originator %pM, neighbor: %pM, last_valid %lu\n", orig_node->orig, neigh_node->addr, (neigh_node->last_valid / HZ));
+                               ((PURGE_TIMEOUT * HZ) / 1000)))) ||
+                   (neigh_node->if_incoming->if_status ==
+                                               IF_TO_BE_REMOVED)) {
+
+                       if (neigh_node->if_incoming->if_status ==
+                                                       IF_TO_BE_REMOVED)
+                               bat_dbg(DBG_BATMAN, "neighbor purge: originator %pM, neighbor: %pM, iface: %s\n",
+                                       orig_node->orig, neigh_node->addr,
+                                       neigh_node->if_incoming->dev);
+                       else
+                               bat_dbg(DBG_BATMAN, "neighbor timeout: originator %pM, neighbor: %pM, last_valid: %lu\n",
+                                       orig_node->orig, neigh_node->addr,
+                                       (neigh_node->last_valid / HZ));
 
                        neigh_purged = true;
                        list_del(list_pos);
@@ -205,7 +218,6 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
        return neigh_purged;
 }
 
-
 static bool purge_orig_node(struct orig_node *orig_node)
 {
        struct neigh_node *best_neigh_node;
@@ -224,6 +236,7 @@ static bool purge_orig_node(struct orig_node *orig_node)
                                      orig_node->hna_buff,
                                      orig_node->hna_buff_len);
        }
+
        return false;
 }
 
@@ -246,7 +259,252 @@ void purge_orig(struct work_struct *work)
 
        spin_unlock_irqrestore(&orig_hash_lock, flags);
 
-       start_purge_timer();
+       /* if work == NULL we were not called by the timer
+        * and thus do not need to re-arm the timer */
+       if (work)
+               start_purge_timer();
 }
 
+ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
+                             size_t count, loff_t off)
+{
+       HASHIT(hashit);
+       struct bat_priv *bat_priv = netdev_priv(net_dev);
+       struct orig_node *orig_node;
+       struct neigh_node *neigh_node;
+       size_t hdr_len, tmp_len;
+       int batman_count = 0, bytes_written = 0;
+       unsigned long flags;
+       char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
+
+       if (!bat_priv->primary_if) {
+               if (off == 0)
+                       return sprintf(buff,
+                                      "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
+                                      net_dev->name);
+
+               return 0;
+       }
+
+       if (bat_priv->primary_if->if_status != IF_ACTIVE) {
+               if (off == 0)
+                       return sprintf(buff,
+                                      "BATMAN mesh %s disabled - primary interface not active\n",
+                                      net_dev->name);
+
+               return 0;
+       }
+
+       rcu_read_lock();
+       hdr_len = sprintf(buff,
+                  "  %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
+                  "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
+                  "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
+                  bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
+                  net_dev->name);
+       rcu_read_unlock();
+
+       if (off < hdr_len)
+               bytes_written = hdr_len;
+
+       spin_lock_irqsave(&orig_hash_lock, flags);
+
+       while (hash_iterate(orig_hash, &hashit)) {
+
+               orig_node = hashit.bucket->data;
+
+               if (!orig_node->router)
+                       continue;
+
+               if (orig_node->router->tq_avg == 0)
+                       continue;
+
+               /* estimated line length */
+               if (count < bytes_written + 200)
+                       break;
+
+               addr_to_string(orig_str, orig_node->orig);
+               addr_to_string(router_str, orig_node->router->addr);
 
+               tmp_len = sprintf(buff + bytes_written,
+                                 "%-17s  (%3i) %17s [%10s]:",
+                                  orig_str, orig_node->router->tq_avg,
+                                  router_str,
+                                  orig_node->router->if_incoming->dev);
+
+               list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
+                       addr_to_string(orig_str, neigh_node->addr);
+                       tmp_len += sprintf(buff + bytes_written + tmp_len,
+                                          " %17s (%3i)", orig_str,
+                                          neigh_node->tq_avg);
+               }
+
+               tmp_len += sprintf(buff + bytes_written + tmp_len, "\n");
+
+               batman_count++;
+               hdr_len += tmp_len;
+
+               if (off >= hdr_len)
+                       continue;
+
+               bytes_written += tmp_len;
+       }
+
+       spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+       if ((batman_count == 0) && (off == 0))
+               bytes_written += sprintf(buff + bytes_written,
+                                       "No batman nodes in range ...\n");
+
+       return bytes_written;
+}
+
+static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
+{
+       void *data_ptr;
+
+       data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS,
+                          GFP_ATOMIC);
+       if (!data_ptr) {
+               printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
+               return -1;
+       }
+
+       memcpy(data_ptr, orig_node->bcast_own,
+              (max_if_num - 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS);
+       kfree(orig_node->bcast_own);
+       orig_node->bcast_own = data_ptr;
+
+       data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
+       if (!data_ptr) {
+               printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
+               return -1;
+       }
+
+       memcpy(data_ptr, orig_node->bcast_own_sum,
+              (max_if_num - 1) * sizeof(uint8_t));
+       kfree(orig_node->bcast_own_sum);
+       orig_node->bcast_own_sum = data_ptr;
+
+       return 0;
+}
+
+int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
+{
+       struct orig_node *orig_node;
+       HASHIT(hashit);
+
+       /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
+        * if_num */
+       spin_lock(&orig_hash_lock);
+
+       while (hash_iterate(orig_hash, &hashit)) {
+               orig_node = hashit.bucket->data;
+
+               if (orig_node_add_if(orig_node, max_if_num) == -1)
+                       goto err;
+       }
+
+       spin_unlock(&orig_hash_lock);
+       return 0;
+
+err:
+       spin_unlock(&orig_hash_lock);
+       return -ENOMEM;
+}
+
+static int orig_node_del_if(struct orig_node *orig_node,
+                    int max_if_num, int del_if_num)
+{
+       void *data_ptr = NULL;
+       int chunk_size;
+
+       /* last interface was removed */
+       if (max_if_num == 0)
+               goto free_bcast_own;
+
+       chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS;
+       data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
+       if (!data_ptr) {
+               printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
+               return -1;
+       }
+
+       /* copy first part */
+       memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
+
+       /* copy second part */
+       memcpy(data_ptr,
+              orig_node->bcast_own + ((del_if_num + 1) * chunk_size),
+              (max_if_num - del_if_num) * chunk_size);
+
+free_bcast_own:
+       kfree(orig_node->bcast_own);
+       orig_node->bcast_own = data_ptr;
+
+       if (max_if_num == 0)
+               goto free_own_sum;
+
+       data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
+       if (!data_ptr) {
+               printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
+               return -1;
+       }
+
+       memcpy(data_ptr, orig_node->bcast_own_sum,
+              del_if_num * sizeof(uint8_t));
+
+       memcpy(data_ptr,
+              orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)),
+              (max_if_num - del_if_num) * sizeof(uint8_t));
+
+free_own_sum:
+       kfree(orig_node->bcast_own_sum);
+       orig_node->bcast_own_sum = data_ptr;
+
+       return 0;
+}
+
+int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
+{
+       struct batman_if *batman_if_tmp;
+       struct orig_node *orig_node;
+       HASHIT(hashit);
+       int ret;
+
+       /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
+        * if_num */
+       spin_lock(&orig_hash_lock);
+
+       while (hash_iterate(orig_hash, &hashit)) {
+               orig_node = hashit.bucket->data;
+
+               ret = orig_node_del_if(orig_node, max_if_num,
+                                      batman_if->if_num);
+
+               if (ret == -1)
+                       goto err;
+       }
+
+       /* renumber remaining batman interfaces _inside_ of orig_hash_lock */
+       rcu_read_lock();
+       list_for_each_entry_rcu(batman_if_tmp, &if_list, list) {
+               if (batman_if_tmp->if_status == IF_NOT_IN_USE)
+                       continue;
+
+               if (batman_if == batman_if_tmp)
+                       continue;
+
+               if (batman_if_tmp->if_num > batman_if->if_num)
+                       batman_if_tmp->if_num--;
+       }
+       rcu_read_unlock();
+
+       batman_if->if_num = -1;
+       spin_unlock(&orig_hash_lock);
+       return 0;
+
+err:
+       spin_unlock(&orig_hash_lock);
+       return -ENOMEM;
+}