diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2010-05-07 21:47:22 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-11 13:42:39 -0700 |
commit | 208e13e4297a1d9b986aa371c4529df7dda1c835 (patch) | |
tree | 037587ed4e6df7004762e6e22593a61dc87c1079 /drivers/staging/batman-adv/originator.c | |
parent | 35bd69d42e2fba4c0fd547e3bf99a0afd5700f76 (diff) | |
download | op-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.c | 193 |
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; +} |