summaryrefslogtreecommitdiffstats
path: root/drivers/staging/batman-adv/originator.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2010-05-07 21:47:22 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-11 13:42:39 -0700
commit208e13e4297a1d9b986aa371c4529df7dda1c835 (patch)
tree037587ed4e6df7004762e6e22593a61dc87c1079 /drivers/staging/batman-adv/originator.c
parent35bd69d42e2fba4c0fd547e3bf99a0afd5700f76 (diff)
downloadop-kernel-dev-208e13e4297a1d9b986aa371c4529df7dda1c835.zip
op-kernel-dev-208e13e4297a1d9b986aa371c4529df7dda1c835.tar.gz
Staging: batman-adv: move /proc interface handling to /sys
Instead of having a single /proc file "interfaces" in which you have to echo the wanted interface batman-adv will create a subfolder in each suitable /sys/class/net folder. This subfolder contains files for the interface specific settings. For example, mesh_iface to add/remove an interface from a virtual mesh network (at the moment only bat0 is supported). Example: echo bat0 > /sys/class/net/eth0/batman-adv/mesh_iface to deactivate: echo none > /sys/class/net/eth0/batman-adv/mesh_iface Interfaces which are not compatible with batman-adv won't contain the batman-adv folder, therefore can't be activated. Not supported are: loopback, non-ethernet, non-ARP and virtual mesh network interfaces Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/batman-adv/originator.c')
-rw-r--r--drivers/staging/batman-adv/originator.c193
1 files changed, 176 insertions, 17 deletions
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c
index 4152701..44bbe89 100644
--- a/drivers/staging/batman-adv/originator.c
+++ b/drivers/staging/batman-adv/originator.c
@@ -118,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;
@@ -139,13 +141,13 @@ struct orig_node *get_orig_node(uint8_t *addr)
orig_node->router = NULL;
orig_node->hna_buff = NULL;
- 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;
@@ -182,16 +184,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);
@@ -246,13 +257,17 @@ 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;
@@ -260,10 +275,7 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
unsigned long flags;
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
- rcu_read_lock();
- if (list_empty(&if_list)) {
- rcu_read_unlock();
-
+ if (!bat_priv->primary_if) {
if (off == 0)
return sprintf(buff,
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
@@ -272,9 +284,7 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
return 0;
}
- if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
- rcu_read_unlock();
-
+ if (bat_priv->primary_if->if_status != IF_ACTIVE) {
if (off == 0)
return sprintf(buff,
"BATMAN mesh %s disabled - primary interface not active\n",
@@ -283,12 +293,12 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
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,
- ((struct batman_if *)if_list.next)->dev,
- ((struct batman_if *)if_list.next)->addr_str,
+ bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
net_dev->name);
rcu_read_unlock();
@@ -347,3 +357,152 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
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;
+}
OpenPOWER on IntegriCloud