Author: marek
Date: 2010-04-05 22:50:43 +0200 (Mon, 05 Apr 2010)
New Revision: 1622
Removed:
trunk/batman-adv-kernelland/proc.c
trunk/batman-adv-kernelland/proc.h
Modified:
trunk/batman-adv-kernelland/Makefile.kbuild
trunk/batman-adv-kernelland/bat_sysfs.c
trunk/batman-adv-kernelland/bat_sysfs.h
trunk/batman-adv-kernelland/device.c
trunk/batman-adv-kernelland/gateway_client.c
trunk/batman-adv-kernelland/hard-interface.c
trunk/batman-adv-kernelland/hard-interface.h
trunk/batman-adv-kernelland/main.c
trunk/batman-adv-kernelland/main.h
trunk/batman-adv-kernelland/originator.c
trunk/batman-adv-kernelland/originator.h
trunk/batman-adv-kernelland/routing.c
trunk/batman-adv-kernelland/send.c
trunk/batman-adv-kernelland/send.h
trunk/batman-adv-kernelland/soft-interface.c
trunk/batman-adv-kernelland/translation-table.c
trunk/batman-adv-kernelland/types.h
trunk/batman-adv-kernelland/vis.c
Log:
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(a)yahoo.de>
Modified: trunk/batman-adv-kernelland/Makefile.kbuild
===================================================================
--- trunk/batman-adv-kernelland/Makefile.kbuild 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/Makefile.kbuild 2010-04-05 20:50:43 UTC (rev 1622)
@@ -32,4 +32,4 @@
endif
obj-m += batman-adv.o
-batman-adv-objs := main.o proc.o bat_sysfs.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 gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o)
+batman-adv-objs := main.o bat_sysfs.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 gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o)
Modified: trunk/batman-adv-kernelland/bat_sysfs.c
===================================================================
--- trunk/batman-adv-kernelland/bat_sysfs.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/bat_sysfs.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -38,6 +38,14 @@
char *buf, size_t count);
};
+struct hardif_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
+ char *buf, size_t count);
+};
+
#define BAT_ATTR(_name, _mode, _show, _store) \
struct bat_attribute bat_attr_##_name = { \
.attr = {.name = __stringify(_name), \
@@ -54,6 +62,14 @@
.write = _write, \
};
+#define HARDIF_ATTR(_name, _mode, _show, _store) \
+struct hardif_attribute hardif_attr_##_name = { \
+ .attr = {.name = __stringify(_name), \
+ .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr,
char *buff)
{
@@ -392,6 +408,8 @@
atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
atomic_set(&bat_priv->gw_class, 0);
atomic_set(&bat_priv->orig_interval, 1000);
+ bat_priv->primary_if = NULL;
+ bat_priv->num_ifaces = 0;
bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
batif_kobject);
@@ -452,3 +470,129 @@
kobject_put(bat_priv->mesh_obj);
bat_priv->mesh_obj = NULL;
}
+
+static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
+ char *buff)
+{
+ struct net_device *net_dev = to_net_dev(to_dev(kobj->parent));
+ struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+
+ if (!batman_if)
+ return 0;
+
+ return sprintf(buff, "status: %s\ncommands: none, bat0 \n",
+ batman_if->if_status == IF_NOT_IN_USE ?
+ "none" : "bat0");
+}
+
+static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
+ char *buff, size_t count)
+{
+ struct net_device *net_dev = to_net_dev(to_dev(kobj->parent));
+ struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+ int status_tmp = -1;
+
+ if (!batman_if)
+ return count;
+
+ if (strncmp(buff, "none", 4) == 0)
+ status_tmp = IF_NOT_IN_USE;
+
+ if (strncmp(buff, "bat0", 4) == 0)
+ status_tmp = IF_I_WANT_YOU;
+
+ if (status_tmp < 0) {
+ if (buff[count - 1] == '\n')
+ buff[count - 1] = '\0';
+
+ printk(KERN_ERR "batman-adv:Invalid parameter for 'mesh_iface' setting received: %s\n",
+ buff);
+ return -EINVAL;
+ }
+
+ if ((batman_if->if_status == status_tmp) ||
+ ((status_tmp == IF_I_WANT_YOU) &&
+ (batman_if->if_status != IF_NOT_IN_USE)))
+ return count;
+
+ if (status_tmp == IF_I_WANT_YOU)
+ status_tmp = hardif_enable_interface(batman_if);
+ else
+ hardif_disable_interface(batman_if);
+
+ return (status_tmp < 0 ? status_tmp : count);
+}
+
+static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
+ char *buff)
+{
+ struct net_device *net_dev = to_net_dev(to_dev(kobj->parent));
+ struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+
+ if (!batman_if)
+ return 0;
+
+ switch (batman_if->if_status) {
+ case IF_TO_BE_REMOVED:
+ return sprintf(buff, "disabling\n");
+ case IF_INACTIVE:
+ return sprintf(buff, "inactive\n");
+ case IF_ACTIVE:
+ return sprintf(buff, "active\n");
+ case IF_TO_BE_ACTIVATED:
+ return sprintf(buff, "enabling\n");
+ case IF_NOT_IN_USE:
+ default:
+ return sprintf(buff, "not in use\n");
+ }
+}
+
+static HARDIF_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
+ show_mesh_iface, store_mesh_iface);
+static HARDIF_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
+
+static struct hardif_attribute *batman_attrs[] = {
+ &hardif_attr_mesh_iface,
+ &hardif_attr_iface_status,
+ NULL,
+};
+
+int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
+{
+ struct kobject *hardif_kobject = &dev->dev.kobj;
+ struct hardif_attribute **hardif_attr;
+ int err;
+
+ *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
+ hardif_kobject);
+
+ if (!*hardif_obj) {
+ printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
+ dev->name, SYSFS_IF_BAT_SUBDIR);
+ goto out;
+ }
+
+ for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) {
+ err = sysfs_create_file(*hardif_obj, &((*hardif_attr)->attr));
+ if (err) {
+ printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
+ dev->name, SYSFS_IF_BAT_SUBDIR,
+ ((*hardif_attr)->attr).name);
+ goto rem_attr;
+ }
+ }
+
+ return 0;
+
+rem_attr:
+ for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr)
+ sysfs_remove_file(*hardif_obj, &((*hardif_attr)->attr));
+out:
+ return -ENOMEM;
+}
+
+void sysfs_del_hardif(struct kobject **hardif_obj)
+{
+ kobject_put(*hardif_obj);
+ *hardif_obj = NULL;
+}
Modified: trunk/batman-adv-kernelland/bat_sysfs.h
===================================================================
--- trunk/batman-adv-kernelland/bat_sysfs.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/bat_sysfs.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -21,6 +21,9 @@
#define SYSFS_IF_MESH_SUBDIR "mesh"
+#define SYSFS_IF_BAT_SUBDIR "batman_adv"
int sysfs_add_meshif(struct net_device *dev);
void sysfs_del_meshif(struct net_device *dev);
+int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
+void sysfs_del_hardif(struct kobject **hardif_obj);
Modified: trunk/batman-adv-kernelland/device.c
===================================================================
--- trunk/batman-adv-kernelland/device.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/device.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -265,7 +265,7 @@
if (!batman_if)
goto dst_unreach;
- if (batman_if->if_active != IF_ACTIVE)
+ if (batman_if->if_status != IF_ACTIVE)
goto dst_unreach;
memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN);
Modified: trunk/batman-adv-kernelland/gateway_client.c
===================================================================
--- trunk/batman-adv-kernelland/gateway_client.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/gateway_client.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -338,12 +338,13 @@
int gw_client_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
+ struct bat_priv *bat_priv = netdev_priv(net_dev);
struct gw_node *gw_node;
size_t hdr_len, tmp_len;
int bytes_written = 0, gw_count = 0;
rcu_read_lock();
- if (list_empty(&if_list)) {
+ if (!bat_priv->primary_if) {
rcu_read_unlock();
if (off == 0)
@@ -354,7 +355,7 @@
return 0;
}
- if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
+ if (bat_priv->primary_if->if_status != IF_ACTIVE) {
rcu_read_unlock();
if (off == 0)
@@ -369,8 +370,8 @@
" %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)] \n",
"Gateway", "#", TQ_MAX_VALUE, "Nexthop",
"outgoingIF", 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();
Modified: trunk/batman-adv-kernelland/hard-interface.c
===================================================================
--- trunk/batman-adv-kernelland/hard-interface.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/hard-interface.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -25,23 +25,22 @@
#include "send.h"
#include "translation-table.h"
#include "routing.h"
+#include "bat_sysfs.h"
+#include "originator.h"
#include "hash.h"
#include "compat.h"
+#include <linux/if_arp.h>
+
#define MIN(x, y) ((x) < (y) ? (x) : (y))
-static char avail_ifs;
-static char active_ifs;
-
-static void hardif_free_interface(struct rcu_head *rcu);
-
-static struct batman_if *get_batman_if_by_name(char *name)
+struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
- if (strncmp(batman_if->dev, name, IFNAMSIZ) == 0)
+ if (batman_if->net_dev == net_dev)
goto out;
}
@@ -52,33 +51,100 @@
return batman_if;
}
-int hardif_min_mtu(void)
+static int is_valid_iface(struct net_device *net_dev)
{
+ if (net_dev->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (net_dev->type != ARPHRD_ETHER)
+ return 0;
+
+ if (net_dev->addr_len != ETH_ALEN)
+ return 0;
+
+ /* no batman over batman */
+#ifdef HAVE_NET_DEVICE_OPS
+ if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
+ return 0;
+#else
+ if (net_dev->hard_start_xmit == interface_tx)
+ return 0;
+#endif
+
+ /* Device is being bridged */
+ /* if (net_dev->br_port != NULL)
+ return 0; */
+
+ return 1;
+}
+
+static struct batman_if *get_active_batman_if(void)
+{
struct batman_if *batman_if;
- /* allow big frames if all devices are capable to do so
- * (have MTU > 1500 + BAT_HEADER_LEN) */
- int min_mtu = ETH_DATA_LEN;
+ /* TODO: should check interfaces belonging to bat_priv */
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
- if ((batman_if->if_active == IF_ACTIVE) ||
- (batman_if->if_active == IF_TO_BE_ACTIVATED))
- min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN,
- min_mtu);
+ if (batman_if->if_status == IF_ACTIVE)
+ goto out;
}
+
+ batman_if = NULL;
+
+out:
rcu_read_unlock();
+ return batman_if;
+}
- return min_mtu;
+static void set_primary_if(struct bat_priv *bat_priv,
+ struct batman_if *batman_if)
+{
+ struct batman_packet *batman_packet;
+
+ bat_priv->primary_if = batman_if;
+
+ if (!bat_priv->primary_if)
+ return;
+
+ set_main_if_addr(batman_if->net_dev->dev_addr);
+
+ batman_packet = (struct batman_packet *)(batman_if->packet_buff);
+ batman_packet->flags = PRIMARIES_FIRST_HOP;
+ batman_packet->ttl = TTL;
+
+ /***
+ * hacky trick to make sure that we send the HNA information via
+ * our new primary interface
+ */
+ atomic_set(&hna_local_changed, 1);
}
+static bool hardif_is_iface_up(struct batman_if *batman_if)
+{
+ if (batman_if->net_dev->flags & IFF_UP)
+ return true;
+
+ return false;
+}
+
+static void update_mac_addresses(struct batman_if *batman_if)
+{
+ addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
+
+ memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
+ batman_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
+ batman_if->net_dev->dev_addr, ETH_ALEN);
+}
+
static void check_known_mac_addr(uint8_t *addr)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
- if ((batman_if->if_active != IF_ACTIVE) &&
- (batman_if->if_active != IF_TO_BE_ACTIVATED))
+ if ((batman_if->if_status != IF_ACTIVE) &&
+ (batman_if->if_status != IF_TO_BE_ACTIVATED))
continue;
if (!compare_orig(batman_if->net_dev->dev_addr, addr))
@@ -91,6 +157,25 @@
rcu_read_unlock();
}
+int hardif_min_mtu(void)
+{
+ struct batman_if *batman_if;
+ /* allow big frames if all devices are capable to do so
+ * (have MTU > 1500 + BAT_HEADER_LEN) */
+ int min_mtu = ETH_DATA_LEN;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(batman_if, &if_list, list) {
+ if ((batman_if->if_status == IF_ACTIVE) ||
+ (batman_if->if_status == IF_TO_BE_ACTIVATED))
+ min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN,
+ min_mtu);
+ }
+ rcu_read_unlock();
+
+ return min_mtu;
+}
+
/* adjusts the MTU if a new interface with a smaller MTU appeared. */
void update_min_mtu(void)
{
@@ -101,322 +186,246 @@
soft_device->mtu = min_mtu;
}
-/* checks if the interface is up. (returns 1 if it is) */
-static int hardif_is_interface_up(char *dev)
+static void hardif_activate_interface(struct bat_priv *bat_priv,
+ struct batman_if *batman_if)
{
- struct net_device *net_dev;
+ if (batman_if->if_status != IF_INACTIVE)
+ return;
+ dev_hold(batman_if->net_dev);
+
+ update_mac_addresses(batman_if);
+ batman_if->if_status = IF_TO_BE_ACTIVATED;
+
/**
- * if we already have an interface in our interface list and
- * the current interface is not the primary interface and
- * the primary interface is not up and
- * the primary interface has never been up - don't activate any
- * secondary interface !
+ * the first active interface becomes our primary interface or
+ * the next active interface after the old primay interface was removed
*/
+ if (!bat_priv->primary_if)
+ set_primary_if(bat_priv, batman_if);
- rcu_read_lock();
- if ((!list_empty(&if_list)) &&
- strncmp(((struct batman_if *)if_list.next)->dev, dev, IFNAMSIZ) &&
- !(((struct batman_if *)if_list.next)->if_active == IF_ACTIVE) &&
- !(((struct batman_if *)if_list.next)->if_active == IF_TO_BE_ACTIVATED) &&
- (!main_if_was_up())) {
- rcu_read_unlock();
- goto end;
- }
- rcu_read_unlock();
+ printk(KERN_INFO "batman-adv:Interface activated: %s\n",
+ batman_if->dev);
-#ifdef __NET_NET_NAMESPACE_H
- net_dev = dev_get_by_name(&init_net, dev);
-#else
- net_dev = dev_get_by_name(dev);
-#endif
- if (!net_dev)
- goto end;
+ if (atomic_read(&module_state) == MODULE_INACTIVE)
+ activate_module();
- if (!(net_dev->flags & IFF_UP))
- goto failure;
-
- dev_put(net_dev);
- return 1;
-
-failure:
- dev_put(net_dev);
-end:
- return 0;
+ update_min_mtu();
+ return;
}
-/* deactivates the interface. */
-void hardif_deactivate_interface(struct batman_if *batman_if)
+static void hardif_deactivate_interface(struct batman_if *batman_if)
{
- if (batman_if->if_active != IF_ACTIVE)
+ if ((batman_if->if_status != IF_ACTIVE) &&
+ (batman_if->if_status != IF_TO_BE_ACTIVATED))
return;
- /**
- * batman_if->net_dev has been acquired by dev_get_by_name() in
- * proc_interfaces_write() and has to be unreferenced.
- */
+ dev_put(batman_if->net_dev);
- if (batman_if->net_dev)
- dev_put(batman_if->net_dev);
+ batman_if->if_status = IF_INACTIVE;
- batman_if->if_active = IF_INACTIVE;
- active_ifs--;
+ printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
+ batman_if->dev);
- printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
- batman_if->dev);
+ update_min_mtu();
}
-/* (re)activate given interface. */
-static void hardif_activate_interface(struct batman_if *batman_if)
+int hardif_enable_interface(struct batman_if *batman_if)
{
- if (batman_if->if_active != IF_INACTIVE)
- return;
+ /* FIXME: each batman_if will be attached to a softif */
+ struct bat_priv *bat_priv = netdev_priv(soft_device);
+ struct batman_packet *batman_packet;
-#ifdef __NET_NET_NAMESPACE_H
- batman_if->net_dev = dev_get_by_name(&init_net, batman_if->dev);
-#else
- batman_if->net_dev = dev_get_by_name(batman_if->dev);
-#endif
- if (!batman_if->net_dev)
- goto dev_err;
+ if (batman_if->if_status != IF_NOT_IN_USE)
+ goto out;
- check_known_mac_addr(batman_if->net_dev->dev_addr);
+ batman_if->packet_len = BAT_PACKET_LEN;
+ batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
- addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
+ if (!batman_if->packet_buff) {
+ printk(KERN_ERR "batman-adv:Can't add interface packet (%s): out of memory\n",
+ batman_if->dev);
+ goto err;
+ }
- memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
- batman_if->net_dev->dev_addr, ETH_ALEN);
- memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
- batman_if->net_dev->dev_addr, ETH_ALEN);
+ batman_packet = (struct batman_packet *)(batman_if->packet_buff);
+ batman_packet->packet_type = BAT_PACKET;
+ batman_packet->version = COMPAT_VERSION;
+ batman_packet->flags = 0;
+ batman_packet->ttl = 2;
+ batman_packet->tq = TQ_MAX_VALUE;
+ batman_packet->num_hna = 0;
- batman_if->if_active = IF_TO_BE_ACTIVATED;
- active_ifs++;
+ batman_if->if_num = bat_priv->num_ifaces;
+ bat_priv->num_ifaces++;
+ batman_if->if_status = IF_INACTIVE;
+ orig_hash_add_if(batman_if, bat_priv->num_ifaces);
- /* save the mac address if it is our primary interface */
- if (batman_if->if_num == 0)
- set_main_if_addr(batman_if->net_dev->dev_addr);
+ atomic_set(&batman_if->seqno, 1);
+ printk(KERN_INFO "batman-adv:Adding interface: %s\n", batman_if->dev);
- printk(KERN_INFO "batman-adv:Interface activated: %s\n",
- batman_if->dev);
+ if (hardif_is_iface_up(batman_if))
+ hardif_activate_interface(bat_priv, batman_if);
+ else
+ printk(KERN_ERR "batman-adv:Not using interface %s (retrying later): interface not active\n", batman_if->dev);
- return;
+ /* begin scheduling originator messages on that interface */
+ schedule_own_packet(batman_if);
-dev_err:
- batman_if->net_dev = NULL;
-}
+out:
+ return 0;
-static void hardif_free_interface(struct rcu_head *rcu)
-{
- struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu);
-
- kfree(batman_if->packet_buff);
- kfree(batman_if->dev);
- kfree(batman_if);
+err:
+ return -ENOMEM;
}
-/**
- * called by
- * - echo '' > /proc/.../interfaces
- * - modprobe -r batman-adv-core
- */
-/* removes and frees all interfaces */
-void hardif_remove_interfaces(void)
+void hardif_disable_interface(struct batman_if *batman_if)
{
- struct batman_if *batman_if = NULL;
+ /* FIXME: each batman_if will be attached to a softif */
+ struct bat_priv *bat_priv = netdev_priv(soft_device);
- avail_ifs = 0;
+ if (batman_if->if_status == IF_ACTIVE)
+ hardif_deactivate_interface(batman_if);
- /* no lock needed - we don't delete somewhere else */
- list_for_each_entry(batman_if, &if_list, list) {
+ if (batman_if->if_status != IF_INACTIVE)
+ return;
- list_del_rcu(&batman_if->list);
+ printk(KERN_INFO "batman-adv:Removing interface: %s\n", batman_if->dev);
+ bat_priv->num_ifaces--;
+ orig_hash_del_if(batman_if, bat_priv->num_ifaces);
- /* first deactivate interface */
- if (batman_if->if_active != IF_INACTIVE)
- hardif_deactivate_interface(batman_if);
+ if (batman_if == bat_priv->primary_if)
+ set_primary_if(bat_priv, get_active_batman_if());
- call_rcu(&batman_if->rcu, hardif_free_interface);
- }
-}
+ kfree(batman_if->packet_buff);
+ batman_if->packet_buff = NULL;
+ batman_if->if_status = IF_NOT_IN_USE;
-static int resize_orig(struct orig_node *orig_node, int if_num)
-{
- void *data_ptr;
-
- data_ptr = kmalloc((if_num + 1) * 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,
- if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS);
- kfree(orig_node->bcast_own);
- orig_node->bcast_own = data_ptr;
-
- data_ptr = kmalloc((if_num + 1) * 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, if_num * sizeof(uint8_t));
- kfree(orig_node->bcast_own_sum);
- orig_node->bcast_own_sum = data_ptr;
-
- return 0;
+ if ((atomic_read(&module_state) == MODULE_ACTIVE) &&
+ (bat_priv->num_ifaces == 0))
+ deactivate_module();
}
-
-/* adds an interface the interface list and activate it, if possible */
-int hardif_add_interface(char *dev, int if_num)
+static struct batman_if *hardif_add_interface(struct net_device *net_dev)
{
struct batman_if *batman_if;
- struct batman_packet *batman_packet;
- struct orig_node *orig_node;
- unsigned long flags;
- HASHIT(hashit);
+ int ret;
- batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);
+ ret = is_valid_iface(net_dev);
+ if (ret != 1)
+ goto out;
+ batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
if (!batman_if) {
- printk(KERN_ERR "batman-adv:Can't add interface (%s): out of memory\n", dev);
- return -1;
+ printk(KERN_ERR "batman-adv:Can't add interface (%s): out of memory\n",
+ net_dev->name);
+ goto out;
}
- batman_if->net_dev = NULL;
+ batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC);
+ if (!batman_if->dev)
+ goto free_if;
- if ((if_num == 0) && (num_hna > 0))
- batman_if->packet_len = BAT_PACKET_LEN + num_hna * ETH_ALEN;
- else
- batman_if->packet_len = BAT_PACKET_LEN;
+ ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev);
+ if (ret)
+ goto free_dev;
- batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL);
-
- if (!batman_if->packet_buff) {
- printk(KERN_ERR "batman-adv:Can't add interface packet (%s): out of memory\n", dev);
- goto out;
- }
-
- batman_if->if_num = if_num;
- batman_if->dev = dev;
- batman_if->if_active = IF_INACTIVE;
+ batman_if->if_num = -1;
+ batman_if->net_dev = net_dev;
+ batman_if->if_status = IF_NOT_IN_USE;
INIT_RCU_HEAD(&batman_if->rcu);
-
- printk(KERN_INFO "batman-adv:Adding interface: %s\n", dev);
- avail_ifs++;
-
INIT_LIST_HEAD(&batman_if->list);
- batman_packet = (struct batman_packet *)(batman_if->packet_buff);
- batman_packet->packet_type = BAT_PACKET;
- batman_packet->version = COMPAT_VERSION;
- batman_packet->flags = batman_if->if_num > 0 ?
- 0x00 : PRIMARIES_FIRST_HOP;
- batman_packet->ttl = batman_if->if_num > 0 ? 2 : TTL;
- batman_packet->tq = TQ_MAX_VALUE;
- batman_packet->num_hna = 0;
+ check_known_mac_addr(batman_if->net_dev->dev_addr);
+ list_add_tail_rcu(&batman_if->list, &if_list);
+ return batman_if;
- if (batman_if->packet_len != BAT_PACKET_LEN) {
- unsigned char *hna_buff;
- int hna_len;
+free_dev:
+ kfree(batman_if->dev);
+free_if:
+ kfree(batman_if);
+out:
+ return NULL;
+}
- hna_buff = batman_if->packet_buff + BAT_PACKET_LEN;
- hna_len = batman_if->packet_len - BAT_PACKET_LEN;
- batman_packet->num_hna = hna_local_fill_buffer(hna_buff,
- hna_len);
- }
+static void hardif_free_interface(struct rcu_head *rcu)
+{
+ struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu);
- atomic_set(&batman_if->seqno, 1);
+ /* delete all references to this batman_if */
+ purge_orig(NULL);
+ purge_outstanding_packets(batman_if);
- /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
- * if_num */
- spin_lock_irqsave(&orig_hash_lock, flags);
+ kfree(batman_if->dev);
+ kfree(batman_if);
+}
- while (hash_iterate(orig_hash, &hashit)) {
- orig_node = hashit.bucket->data;
- if (resize_orig(orig_node, if_num) == -1) {
- spin_unlock_irqrestore(&orig_hash_lock, flags);
- goto out;
- }
- }
+static void hardif_remove_interface(struct batman_if *batman_if)
+{
+ /* first deactivate interface */
+ if (batman_if->if_status != IF_NOT_IN_USE)
+ hardif_disable_interface(batman_if);
- spin_unlock_irqrestore(&orig_hash_lock, flags);
+ if (batman_if->if_status != IF_NOT_IN_USE)
+ return;
- if (!hardif_is_interface_up(batman_if->dev))
- printk(KERN_ERR "batman-adv:Not using interface %s (retrying later): interface not active\n", batman_if->dev);
- else
- hardif_activate_interface(batman_if);
-
- list_add_tail_rcu(&batman_if->list, &if_list);
-
- /* begin sending originator messages on that interface */
- schedule_own_packet(batman_if);
- return 1;
-
-out:
- kfree(batman_if->packet_buff);
- kfree(batman_if);
- kfree(dev);
- return -1;
+ batman_if->if_status = IF_TO_BE_REMOVED;
+ list_del_rcu(&batman_if->list);
+ sysfs_del_hardif(&batman_if->hardif_obj);
+ call_rcu(&batman_if->rcu, hardif_free_interface);
}
-char hardif_get_active_if_num(void)
+void hardif_remove_interfaces(void)
{
- return active_ifs;
+ struct batman_if *batman_if, *batman_if_tmp;
+
+ list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list)
+ hardif_remove_interface(batman_if);
}
static int hard_if_event(struct notifier_block *this,
- unsigned long event, void *ptr)
+ unsigned long event, void *ptr)
{
- struct net_device *dev = (struct net_device *)ptr;
- struct batman_if *batman_if = get_batman_if_by_name(dev->name);
+ struct net_device *net_dev = (struct net_device *)ptr;
+ struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+ /* FIXME: each batman_if will be attached to a softif */
+ struct bat_priv *bat_priv = netdev_priv(soft_device);
if (!batman_if)
+ batman_if = hardif_add_interface(net_dev);
+
+ if (!batman_if)
goto out;
switch (event) {
+ case NETDEV_REGISTER:
+ break;
+ case NETDEV_UP:
+ hardif_activate_interface(bat_priv, batman_if);
+ break;
case NETDEV_GOING_DOWN:
case NETDEV_DOWN:
- case NETDEV_UNREGISTER:
hardif_deactivate_interface(batman_if);
break;
- case NETDEV_UP:
- hardif_activate_interface(batman_if);
- if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
- (hardif_get_active_if_num() > 0)) {
- activate_module();
- }
+ case NETDEV_UNREGISTER:
+ hardif_remove_interface(batman_if);
break;
- /* NETDEV_CHANGEADDR - mac address change - what are we doing here ? */
+ case NETDEV_CHANGENAME:
+ break;
+ case NETDEV_CHANGEADDR:
+ check_known_mac_addr(batman_if->net_dev->dev_addr);
+ update_mac_addresses(batman_if);
+ if (batman_if == bat_priv->primary_if)
+ set_primary_if(bat_priv, batman_if);
+ break;
default:
break;
};
- update_min_mtu();
-
out:
return NOTIFY_DONE;
}
-/* find batman interface by netdev. assumes rcu_read_lock on */
-static struct batman_if *find_batman_if(struct net_device *dev)
-{
- struct batman_if *batman_if;
-
- rcu_read_lock();
- list_for_each_entry_rcu(batman_if, &if_list, list) {
- if (batman_if->net_dev == dev) {
- rcu_read_unlock();
- return batman_if;
- }
- }
- rcu_read_unlock();
- return NULL;
-}
-
-
/* receive a packet with the batman ethertype coming on a hard
* interface */
int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
@@ -445,12 +454,12 @@
|| !skb_mac_header(skb)))
goto err_free;
- batman_if = find_batman_if(skb->dev);
+ batman_if = get_batman_if_by_netdev(skb->dev);
if (!batman_if)
goto err_free;
/* discard frames on not active interfaces */
- if (batman_if->if_active != IF_ACTIVE)
+ if (batman_if->if_status != IF_ACTIVE)
goto err_free;
stats = (struct net_device_stats *)dev_get_stats(skb->dev);
Modified: trunk/batman-adv-kernelland/hard-interface.h
===================================================================
--- trunk/batman-adv-kernelland/hard-interface.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/hard-interface.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -19,19 +19,19 @@
*
*/
-#define IF_INACTIVE 0
-#define IF_ACTIVE 1
-/* #define IF_TO_BE_DEACTIVATED 2 - not needed anymore */
-#define IF_TO_BE_ACTIVATED 3
+#define IF_NOT_IN_USE 0
+#define IF_TO_BE_REMOVED 1
+#define IF_INACTIVE 2
+#define IF_ACTIVE 3
+#define IF_TO_BE_ACTIVATED 4
+#define IF_I_WANT_YOU 5
extern struct notifier_block hard_if_notifier;
+struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev);
+int hardif_enable_interface(struct batman_if *batman_if);
+void hardif_disable_interface(struct batman_if *batman_if);
void hardif_remove_interfaces(void);
-int hardif_add_interface(char *dev, int if_num);
-void hardif_deactivate_interface(struct batman_if *batman_if);
-char hardif_get_active_if_num(void);
-void hardif_check_interfaces_status(void);
-void hardif_check_interfaces_status_wq(struct work_struct *work);
int batman_skb_recv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *ptype,
Modified: trunk/batman-adv-kernelland/main.c
===================================================================
--- trunk/batman-adv-kernelland/main.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/main.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -20,7 +20,6 @@
*/
#include "main.h"
-#include "proc.h"
#include "bat_sysfs.h"
#include "routing.h"
#include "send.h"
@@ -46,7 +45,6 @@
atomic_t vis_interval;
int16_t num_hna;
-int16_t num_ifs;
struct net_device *soft_device;
@@ -91,10 +89,6 @@
if (!bat_event_workqueue)
return -ENOMEM;
- retval = setup_procfs();
- if (retval < 0)
- return retval;
-
bat_device_init();
/* initialize layer 2 interface */
@@ -137,8 +131,11 @@
void cleanup_module(void)
{
- shutdown_module();
+ deactivate_module();
+ unregister_netdevice_notifier(&hard_if_notifier);
+ hardif_remove_interfaces();
+
if (soft_device) {
sysfs_del_meshif(soft_device);
unregister_netdev(soft_device);
@@ -147,9 +144,6 @@
dev_remove_pack(&batman_adv_packet_type);
- unregister_netdevice_notifier(&hard_if_notifier);
- cleanup_procfs();
-
destroy_workqueue(bat_event_workqueue);
bat_event_workqueue = NULL;
}
@@ -180,17 +174,17 @@
err:
printk(KERN_ERR "batman-adv:Unable to allocate memory for mesh information structures: out of mem ?\n");
- shutdown_module();
+ deactivate_module();
end:
return;
}
/* shuts down the whole module.*/
-void shutdown_module(void)
+void deactivate_module(void)
{
atomic_set(&module_state, MODULE_DEACTIVATING);
- purge_outstanding_packets();
+ purge_outstanding_packets(NULL);
flush_workqueue(bat_event_workqueue);
vis_quit();
@@ -206,7 +200,6 @@
synchronize_net();
bat_device_destroy();
- hardif_remove_interfaces();
synchronize_rcu();
atomic_set(&module_state, MODULE_INACTIVE);
}
Modified: trunk/batman-adv-kernelland/main.h
===================================================================
--- trunk/batman-adv-kernelland/main.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/main.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -133,7 +133,6 @@
extern atomic_t vis_interval;
extern int16_t num_hna;
-extern int16_t num_ifs;
extern struct net_device *soft_device;
@@ -142,7 +141,7 @@
extern struct workqueue_struct *bat_event_workqueue;
void activate_module(void);
-void shutdown_module(void);
+void deactivate_module(void);
void inc_module_count(void);
void dec_module_count(void);
int addr_to_string(char *buff, uint8_t *addr);
Modified: trunk/batman-adv-kernelland/originator.c
===================================================================
--- trunk/batman-adv-kernelland/originator.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/originator.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -120,6 +120,8 @@
* 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;
@@ -141,13 +143,13 @@
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;
@@ -184,16 +186,25 @@
*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)))) {
+ ((PURGE_TIMEOUT * HZ) / 1000)))) ||
+ (neigh_node->if_incoming->if_status ==
+ IF_TO_BE_REMOVED)) {
- 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));
+ 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);
@@ -257,13 +268,18 @@
gw_node_purge_deleted();
gw_election();
- 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;
@@ -271,10 +287,7 @@
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",
@@ -283,9 +296,7 @@
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",
@@ -294,12 +305,12 @@
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();
@@ -357,3 +368,153 @@
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;
+}
Modified: trunk/batman-adv-kernelland/originator.h
===================================================================
--- trunk/batman-adv-kernelland/originator.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/originator.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -30,3 +30,5 @@
uint8_t *neigh, struct batman_if *if_incoming);
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off);
+int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
+int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
Deleted: trunk/batman-adv-kernelland/proc.c
===================================================================
--- trunk/batman-adv-kernelland/proc.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/proc.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2007-2010 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
- *
- */
-
-#include "main.h"
-#include "proc.h"
-#include "routing.h"
-#include "translation-table.h"
-#include "hard-interface.h"
-#include "types.h"
-#include "hash.h"
-#include "vis.h"
-#include "compat.h"
-#include "gateway_common.h"
-#include "gateway_client.h"
-
-static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
-
-static int proc_interfaces_read(struct seq_file *seq, void *offset)
-{
- struct batman_if *batman_if;
-
- rcu_read_lock();
- list_for_each_entry_rcu(batman_if, &if_list, list) {
- seq_printf(seq, "[%8s] %s %s\n",
- (batman_if->if_active == IF_ACTIVE ?
- "active" : "inactive"),
- batman_if->dev,
- (batman_if->if_active == IF_ACTIVE ?
- batman_if->addr_str : " "));
- }
- rcu_read_unlock();
-
- return 0;
-}
-
-static int proc_interfaces_open(struct inode *inode, struct file *file)
-{
- return single_open(file, proc_interfaces_read, NULL);
-}
-
-static ssize_t proc_interfaces_write(struct file *instance,
- const char __user *userbuffer,
- size_t count, loff_t *data)
-{
- char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
- int not_copied = 0, if_num = 0, add_success;
- struct batman_if *batman_if = NULL;
-
- if_string = kmalloc(count, GFP_KERNEL);
-
- if (!if_string)
- return -ENOMEM;
-
- if (count > IFNAMSIZ - 1) {
- printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n");
- goto end;
- }
-
- not_copied = copy_from_user(if_string, userbuffer, count);
- if_string[count - not_copied - 1] = 0;
-
- colon_ptr = strchr(if_string, ':');
- if (colon_ptr)
- *colon_ptr = 0;
-
- if (!colon_ptr) {
- cr_ptr = strchr(if_string, '\n');
- if (cr_ptr)
- *cr_ptr = 0;
- }
-
- if (strlen(if_string) == 0) {
- shutdown_module();
- num_ifs = 0;
- goto end;
- }
-
- /* add interface */
- rcu_read_lock();
- list_for_each_entry_rcu(batman_if, &if_list, list) {
- if (strncmp(batman_if->dev, if_string, count) == 0) {
- printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string);
- rcu_read_unlock();
- goto end;
-
- }
-
- if_num++;
- }
- rcu_read_unlock();
-
- add_success = hardif_add_interface(if_string, if_num);
- if (add_success < 0)
- goto end;
-
- num_ifs = if_num + 1;
-
- if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
- (hardif_get_active_if_num() > 0))
- activate_module();
-
- return count;
-end:
- kfree(if_string);
- return count;
-}
-
-static const struct file_operations proc_interfaces_fops = {
- .owner = THIS_MODULE,
- .open = proc_interfaces_open,
- .read = seq_read,
- .write = proc_interfaces_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-void cleanup_procfs(void)
-{
- if (proc_interface_file)
- remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
-
- if (proc_batman_dir)
-#ifdef __NET_NET_NAMESPACE_H
- remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net);
-#else
- remove_proc_entry(PROC_ROOT_DIR, proc_net);
-#endif
-}
-
-int setup_procfs(void)
-{
-#ifdef __NET_NET_NAMESPACE_H
- proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net);
-#else
- proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net);
-#endif
-
- if (!proc_batman_dir) {
- printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR);
- return -EFAULT;
- }
-
- proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES,
- S_IWUSR | S_IRUGO,
- proc_batman_dir);
- if (proc_interface_file) {
- proc_interface_file->proc_fops = &proc_interfaces_fops;
- } else {
- printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES);
- cleanup_procfs();
- return -EFAULT;
- }
-
- return 0;
-}
Deleted: trunk/batman-adv-kernelland/proc.h
===================================================================
--- trunk/batman-adv-kernelland/proc.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/proc.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2007-2010 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
- *
- */
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#define PROC_ROOT_DIR "batman-adv"
-#define PROC_FILE_INTERFACES "interfaces"
-
-void cleanup_procfs(void);
-int setup_procfs(void);
-
Modified: trunk/batman-adv-kernelland/routing.c
===================================================================
--- trunk/batman-adv-kernelland/routing.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/routing.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -207,7 +207,7 @@
batman_packet->tq = ((batman_packet->tq *
orig_neigh_node->tq_own *
orig_neigh_node->tq_asym_penalty) /
- (TQ_MAX_VALUE * TQ_MAX_VALUE));
+ (TQ_MAX_VALUE * TQ_MAX_VALUE));
bat_dbg(DBG_BATMAN, "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i\n",
orig_node->orig, orig_neigh_node->orig, total_count,
@@ -516,7 +516,7 @@
batman_packet->version, has_directlink_flag);
list_for_each_entry_rcu(batman_if, &if_list, list) {
- if (batman_if->if_active != IF_ACTIVE)
+ if (batman_if->if_status != IF_ACTIVE)
continue;
if (compare_orig(ethhdr->h_source,
@@ -1100,7 +1100,7 @@
if (is_my_mac(ethhdr->h_source))
return NET_RX_DROP;
- bcast_packet = (struct bcast_packet *) skb->data;
+ bcast_packet = (struct bcast_packet *)skb->data;
/* ignore broadcasts originated by myself */
if (is_my_mac(bcast_packet->orig))
Modified: trunk/batman-adv-kernelland/send.c
===================================================================
--- trunk/batman-adv-kernelland/send.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/send.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -60,7 +60,7 @@
{
struct ethhdr *ethhdr;
- if (batman_if->if_active != IF_ACTIVE)
+ if (batman_if->if_status != IF_ACTIVE)
goto send_skb_err;
if (unlikely(!batman_if->net_dev))
@@ -126,7 +126,7 @@
int16_t buff_pos;
struct batman_packet *batman_packet;
- if (batman_if->if_active != IF_ACTIVE)
+ if (batman_if->if_status != IF_ACTIVE)
return;
packet_num = buff_pos = 0;
@@ -184,7 +184,7 @@
return;
}
- if (forw_packet->if_incoming->if_active != IF_ACTIVE)
+ if (forw_packet->if_incoming->if_status != IF_ACTIVE)
return;
/* multihomed peer assumed */
@@ -245,8 +245,14 @@
struct bat_priv *bat_priv = netdev_priv(soft_device);
unsigned long send_time;
struct batman_packet *batman_packet;
- int vis_server = atomic_read(&bat_priv->vis_mode);
+ int vis_server;
+ if ((batman_if->if_status == IF_NOT_IN_USE) ||
+ (batman_if->if_status == IF_TO_BE_REMOVED))
+ return;
+
+ vis_server = atomic_read(&bat_priv->vis_mode);
+
/**
* the interface gets activated here to avoid race conditions between
* the moment of activating the interface in
@@ -254,11 +260,12 @@
* outdated packets (especially uninitialized mac addresses) in the
* packet queue
*/
- if (batman_if->if_active == IF_TO_BE_ACTIVATED)
- batman_if->if_active = IF_ACTIVE;
+ if (batman_if->if_status == IF_TO_BE_ACTIVATED)
+ batman_if->if_status = IF_ACTIVE;
/* if local hna has changed and interface is a primary interface */
- if ((atomic_read(&hna_local_changed)) && (batman_if->if_num == 0))
+ if ((atomic_read(&hna_local_changed)) &&
+ (batman_if == bat_priv->primary_if))
rebuild_batman_packet(batman_if);
/**
@@ -384,13 +391,11 @@
forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
if (!forw_packet)
- return;
+ goto out;
skb = skb_copy(skb, GFP_ATOMIC);
- if (!skb) {
- kfree(forw_packet);
- return;
- }
+ if (!skb)
+ goto packet_free;
skb_reset_mac_header(skb);
@@ -401,6 +406,12 @@
forw_packet->num_packets = 0;
_add_bcast_packet_to_list(forw_packet, 1);
+ return;
+
+packet_free:
+ kfree(forw_packet);
+out:
+ return;
}
void send_outstanding_bcast_packet(struct work_struct *work)
@@ -465,19 +476,31 @@
forw_packet_free(forw_packet);
}
-void purge_outstanding_packets(void)
+void purge_outstanding_packets(struct batman_if *batman_if)
{
struct forw_packet *forw_packet;
struct hlist_node *tmp_node, *safe_tmp_node;
unsigned long flags;
- bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
+ if (batman_if)
+ bat_dbg(DBG_BATMAN, "purge_outstanding_packets(): %s\n",
+ batman_if->dev);
+ else
+ bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
/* free bcast list */
spin_lock_irqsave(&forw_bcast_list_lock, flags);
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&forw_bcast_list, list) {
+ /**
+ * if purge_outstanding_packets() was called with an argmument
+ * we delete only packets belonging to the given interface
+ */
+ if ((batman_if) &&
+ (forw_packet->if_incoming != batman_if))
+ continue;
+
spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/**
@@ -494,6 +517,14 @@
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&forw_bat_list, list) {
+ /**
+ * if purge_outstanding_packets() was called with an argmument
+ * we delete only packets belonging to the given interface
+ */
+ if ((batman_if) &&
+ (forw_packet->if_incoming != batman_if))
+ continue;
+
spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/**
Modified: trunk/batman-adv-kernelland/send.h
===================================================================
--- trunk/batman-adv-kernelland/send.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/send.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -36,4 +36,4 @@
void add_bcast_packet_to_list(struct sk_buff *skb);
void send_outstanding_bcast_packet(struct work_struct *work);
void send_outstanding_bat_packet(struct work_struct *work);
-void purge_outstanding_packets(void);
+void purge_outstanding_packets(struct batman_if *batman_if);
Modified: trunk/batman-adv-kernelland/soft-interface.c
===================================================================
--- trunk/batman-adv-kernelland/soft-interface.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/soft-interface.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -176,8 +176,6 @@
return 0;
}
-
-
int interface_tx(struct sk_buff *skb, struct net_device *dev)
{
struct unicast_packet *unicast_packet;
@@ -263,7 +261,7 @@
spin_unlock_irqrestore(&orig_hash_lock, flags);
- if (batman_if->if_active != IF_ACTIVE)
+ if (batman_if->if_status != IF_ACTIVE)
goto dropped;
if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
Modified: trunk/batman-adv-kernelland/translation-table.c
===================================================================
--- trunk/batman-adv-kernelland/translation-table.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/translation-table.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -160,16 +160,14 @@
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
+ struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hna_local_entry *hna_local_entry;
HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;
size_t hdr_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",
@@ -177,7 +175,6 @@
return 0;
}
- rcu_read_unlock();
hdr_len = sprintf(buff,
"Locally retrieved addresses (from %s) announced via HNA:\n",
@@ -377,16 +374,14 @@
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
+ struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hna_global_entry *hna_global_entry;
HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;
size_t hdr_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",
@@ -394,7 +389,6 @@
return 0;
}
- rcu_read_unlock();
hdr_len = sprintf(buff,
"Globally announced HNAs received via the mesh %s (translation table):\n",
Modified: trunk/batman-adv-kernelland/types.h
===================================================================
--- trunk/batman-adv-kernelland/types.h 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/types.h 2010-04-05 20:50:43 UTC (rev 1622)
@@ -36,12 +36,13 @@
struct list_head list;
int16_t if_num;
char *dev;
- char if_active;
+ char if_status;
char addr_str[ETH_STR_LEN];
struct net_device *net_dev;
atomic_t seqno;
unsigned char *packet_buff;
int packet_len;
+ struct kobject *hardif_obj;
struct rcu_head rcu;
};
@@ -99,6 +100,8 @@
atomic_t gw_mode;
atomic_t gw_class;
atomic_t orig_interval;
+ char num_ifaces;
+ struct batman_if *primary_if;
struct kobject *mesh_obj;
};
Modified: trunk/batman-adv-kernelland/vis.c
===================================================================
--- trunk/batman-adv-kernelland/vis.c 2010-04-05 20:50:39 UTC (rev 1621)
+++ trunk/batman-adv-kernelland/vis.c 2010-04-05 20:50:43 UTC (rev 1622)
@@ -174,13 +174,10 @@
unsigned long flags;
int vis_server = atomic_read(&bat_priv->vis_mode);
- rcu_read_lock();
- if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) {
- rcu_read_unlock();
+ if ((!bat_priv->primary_if) ||
+ (vis_server == VIS_TYPE_CLIENT_UPDATE))
return 0;
- }
- rcu_read_unlock();
hdr_len = 0;
spin_lock_irqsave(&vis_hash_lock, flags);