1
0
Fork 0
alistair23-linux/drivers/staging/batman-adv/main.c

288 lines
6.0 KiB
C
Raw Normal View History

/*
* 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
*
*/
#include "main.h"
#include "proc.h"
#include "routing.h"
#include "send.h"
#include "originator.h"
#include "soft-interface.h"
#include "device.h"
#include "translation-table.h"
#include "hard-interface.h"
#include "types.h"
#include "vis.h"
#include "hash.h"
struct list_head if_list;
struct hlist_head forw_bat_list;
struct hlist_head forw_bcast_list;
struct hashtable_t *orig_hash;
DEFINE_SPINLOCK(orig_hash_lock);
DEFINE_SPINLOCK(forw_bat_list_lock);
DEFINE_SPINLOCK(forw_bcast_list_lock);
atomic_t originator_interval;
atomic_t vis_interval;
atomic_t vis_mode;
atomic_t aggregation_enabled;
int16_t num_hna;
int16_t num_ifs;
struct net_device *soft_device;
unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
atomic_t module_state;
Staging: batman-adv: receive packets directly using skbs This patch removes the (ugly and racy) packet receiving thread and the kernel socket usage. Instead, packets are received directly by registering the ethernet type and handling skbs instead of self-allocated buffers. Some consequences and comments: * we don't copy the payload data when forwarding/sending/receiving data anymore. This should boost performance. * packets from/to different interfaces can be (theoretically) processed simultaneously. Only the big originator hash lock might be in the way. * no more polling or sleeping/wakeup/scheduling issues when receiving packets * this might introduce new race conditions. * aggregation and vis code still use packet buffers and are not (yet) converted. * all spinlocks were converted to irqsave/restore versions to solve some lifelock issues when preempted. This might be overkill, some of these locks might be reverted later. * skb copies are only done if neccesary to avoid overhead performance differences: * we made some "benchmarks" with intel laptops. * bandwidth on Gigabit Ethernet increased from ~500 MBit/s to ~920 MBit/s * ping latency decresed from ~2ms to ~0.2 ms I did some tests on my 9 node qemu environment and could confirm that usual sending/receiving, forwarding, vis, batctl ping etc works. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Acked-by: Sven Eckelmann <sven.eckelmann@gmx.de> Acked-by: Marek Lindner <lindner_marek@yahoo.de> Acked-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-01-02 03:30:48 -07:00
static struct packet_type batman_adv_packet_type __read_mostly = {
.type = __constant_htons(ETH_P_BATMAN),
Staging: batman-adv: receive packets directly using skbs This patch removes the (ugly and racy) packet receiving thread and the kernel socket usage. Instead, packets are received directly by registering the ethernet type and handling skbs instead of self-allocated buffers. Some consequences and comments: * we don't copy the payload data when forwarding/sending/receiving data anymore. This should boost performance. * packets from/to different interfaces can be (theoretically) processed simultaneously. Only the big originator hash lock might be in the way. * no more polling or sleeping/wakeup/scheduling issues when receiving packets * this might introduce new race conditions. * aggregation and vis code still use packet buffers and are not (yet) converted. * all spinlocks were converted to irqsave/restore versions to solve some lifelock issues when preempted. This might be overkill, some of these locks might be reverted later. * skb copies are only done if neccesary to avoid overhead performance differences: * we made some "benchmarks" with intel laptops. * bandwidth on Gigabit Ethernet increased from ~500 MBit/s to ~920 MBit/s * ping latency decresed from ~2ms to ~0.2 ms I did some tests on my 9 node qemu environment and could confirm that usual sending/receiving, forwarding, vis, batctl ping etc works. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Acked-by: Sven Eckelmann <sven.eckelmann@gmx.de> Acked-by: Marek Lindner <lindner_marek@yahoo.de> Acked-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-01-02 03:30:48 -07:00
.func = batman_skb_recv,
};
struct workqueue_struct *bat_event_workqueue;
#ifdef CONFIG_BATMAN_ADV_DEBUG
int debug;
module_param(debug, int, 0644);
int bat_debug_type(int type)
{
return debug & type;
}
#endif
int init_module(void)
{
int retval;
INIT_LIST_HEAD(&if_list);
INIT_HLIST_HEAD(&forw_bat_list);
INIT_HLIST_HEAD(&forw_bcast_list);
atomic_set(&module_state, MODULE_INACTIVE);
atomic_set(&originator_interval, 1000);
atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
* for debugging now. */
atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
atomic_set(&aggregation_enabled, 1);
/* the name should not be longer than 10 chars - see
* http://lwn.net/Articles/23634/ */
bat_event_workqueue = create_singlethread_workqueue("bat_events");
if (!bat_event_workqueue)
return -ENOMEM;
retval = setup_procfs();
if (retval < 0)
return retval;
bat_device_init();
/* initialize layer 2 interface */
soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
interface_setup);
if (!soft_device) {
printk(KERN_ERR "batman-adv:Unable to allocate the batman interface\n");
goto end;
}
retval = register_netdev(soft_device);
if (retval < 0) {
printk(KERN_ERR "batman-adv:Unable to register the batman interface: %i\n", retval);
goto free_soft_device;
}
register_netdevice_notifier(&hard_if_notifier);
Staging: batman-adv: receive packets directly using skbs This patch removes the (ugly and racy) packet receiving thread and the kernel socket usage. Instead, packets are received directly by registering the ethernet type and handling skbs instead of self-allocated buffers. Some consequences and comments: * we don't copy the payload data when forwarding/sending/receiving data anymore. This should boost performance. * packets from/to different interfaces can be (theoretically) processed simultaneously. Only the big originator hash lock might be in the way. * no more polling or sleeping/wakeup/scheduling issues when receiving packets * this might introduce new race conditions. * aggregation and vis code still use packet buffers and are not (yet) converted. * all spinlocks were converted to irqsave/restore versions to solve some lifelock issues when preempted. This might be overkill, some of these locks might be reverted later. * skb copies are only done if neccesary to avoid overhead performance differences: * we made some "benchmarks" with intel laptops. * bandwidth on Gigabit Ethernet increased from ~500 MBit/s to ~920 MBit/s * ping latency decresed from ~2ms to ~0.2 ms I did some tests on my 9 node qemu environment and could confirm that usual sending/receiving, forwarding, vis, batctl ping etc works. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Acked-by: Sven Eckelmann <sven.eckelmann@gmx.de> Acked-by: Marek Lindner <lindner_marek@yahoo.de> Acked-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-01-02 03:30:48 -07:00
dev_add_pack(&batman_adv_packet_type);
printk(KERN_INFO "batman-adv:B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
return 0;
free_soft_device:
free_netdev(soft_device);
soft_device = NULL;
end:
return -ENOMEM;
}
void cleanup_module(void)
{
shutdown_module();
if (soft_device) {
unregister_netdev(soft_device);
soft_device = NULL;
}
Staging: batman-adv: receive packets directly using skbs This patch removes the (ugly and racy) packet receiving thread and the kernel socket usage. Instead, packets are received directly by registering the ethernet type and handling skbs instead of self-allocated buffers. Some consequences and comments: * we don't copy the payload data when forwarding/sending/receiving data anymore. This should boost performance. * packets from/to different interfaces can be (theoretically) processed simultaneously. Only the big originator hash lock might be in the way. * no more polling or sleeping/wakeup/scheduling issues when receiving packets * this might introduce new race conditions. * aggregation and vis code still use packet buffers and are not (yet) converted. * all spinlocks were converted to irqsave/restore versions to solve some lifelock issues when preempted. This might be overkill, some of these locks might be reverted later. * skb copies are only done if neccesary to avoid overhead performance differences: * we made some "benchmarks" with intel laptops. * bandwidth on Gigabit Ethernet increased from ~500 MBit/s to ~920 MBit/s * ping latency decresed from ~2ms to ~0.2 ms I did some tests on my 9 node qemu environment and could confirm that usual sending/receiving, forwarding, vis, batctl ping etc works. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Acked-by: Sven Eckelmann <sven.eckelmann@gmx.de> Acked-by: Marek Lindner <lindner_marek@yahoo.de> Acked-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-01-02 03:30:48 -07:00
dev_remove_pack(&batman_adv_packet_type);
unregister_netdevice_notifier(&hard_if_notifier);
cleanup_procfs();
destroy_workqueue(bat_event_workqueue);
bat_event_workqueue = NULL;
}
/* activates the module, creates bat device, starts timer ... */
void activate_module(void)
{
if (originator_init() < 1)
goto err;
if (hna_local_init() < 1)
goto err;
if (hna_global_init() < 1)
goto err;
hna_local_add(soft_device->dev_addr);
if (bat_device_setup() < 1)
goto end;
if (vis_init() < 1)
goto err;
update_min_mtu();
atomic_set(&module_state, MODULE_ACTIVE);
goto end;
err:
printk(KERN_ERR "batman-adv:Unable to allocate memory for mesh information structures: out of mem ?\n");
shutdown_module();
end:
return;
}
/* shuts down the whole module.*/
void shutdown_module(void)
{
atomic_set(&module_state, MODULE_DEACTIVATING);
purge_outstanding_packets();
flush_workqueue(bat_event_workqueue);
vis_quit();
Staging: batman-adv: receive packets directly using skbs This patch removes the (ugly and racy) packet receiving thread and the kernel socket usage. Instead, packets are received directly by registering the ethernet type and handling skbs instead of self-allocated buffers. Some consequences and comments: * we don't copy the payload data when forwarding/sending/receiving data anymore. This should boost performance. * packets from/to different interfaces can be (theoretically) processed simultaneously. Only the big originator hash lock might be in the way. * no more polling or sleeping/wakeup/scheduling issues when receiving packets * this might introduce new race conditions. * aggregation and vis code still use packet buffers and are not (yet) converted. * all spinlocks were converted to irqsave/restore versions to solve some lifelock issues when preempted. This might be overkill, some of these locks might be reverted later. * skb copies are only done if neccesary to avoid overhead performance differences: * we made some "benchmarks" with intel laptops. * bandwidth on Gigabit Ethernet increased from ~500 MBit/s to ~920 MBit/s * ping latency decresed from ~2ms to ~0.2 ms I did some tests on my 9 node qemu environment and could confirm that usual sending/receiving, forwarding, vis, batctl ping etc works. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Acked-by: Sven Eckelmann <sven.eckelmann@gmx.de> Acked-by: Marek Lindner <lindner_marek@yahoo.de> Acked-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-01-02 03:30:48 -07:00
/* TODO: unregister BATMAN pack */
originator_free();
hna_local_free();
hna_global_free();
synchronize_net();
bat_device_destroy();
hardif_remove_interfaces();
synchronize_rcu();
atomic_set(&module_state, MODULE_INACTIVE);
}
void inc_module_count(void)
{
try_module_get(THIS_MODULE);
}
void dec_module_count(void)
{
module_put(THIS_MODULE);
}
int addr_to_string(char *buff, uint8_t *addr)
{
return sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
}
/* returns 1 if they are the same originator */
int compare_orig(void *data1, void *data2)
{
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}
/* hashfunction to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
int choose_orig(void *data, int32_t size)
{
unsigned char *key = data;
uint32_t hash = 0;
size_t i;
for (i = 0; i < 6; i++) {
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash % size;
}
int is_my_mac(uint8_t *addr)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if ((batman_if->net_dev) &&
(compare_orig(batman_if->net_dev->dev_addr, addr))) {
rcu_read_unlock();
return 1;
}
}
rcu_read_unlock();
return 0;
}
int is_bcast(uint8_t *addr)
{
return (addr[0] == (uint8_t)0xff) && (addr[1] == (uint8_t)0xff);
}
int is_mcast(uint8_t *addr)
{
return *addr & 0x01;
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
#ifdef REVISION_VERSION
MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
#else
MODULE_VERSION(SOURCE_VERSION);
#endif