Hi,
I hope that the fever-induced dreams are over now. Otherwise I will try to write my mails also as little tales. ;)
Nevertheless, I would like to send some patches for 2.6.37. That is not 100% true. We would also like to see the revert 'Revert: "Staging: batman-adv: Adding netfilter-bridge hooks"' too in 2.6.36. It fixes a bug introduced by the commit we revert here.
The rest is more or less the usual stuff, but more feature patches this time. All patches we depend on are already part of 2.6.36-rc3.
I will try to sent a patch again to David S. Miller.
thanks, Sven
Andreas Langer (1): Staging: batman-adv: layer2 unicast packet fragmentation
Marek Lindner (4): Staging: batman-adv: refactoring unicast payload code Staging: batman-adv: register the batman-adv packet type per interface Staging: batman-adv: attach each hard-interface to a soft-interface Staging: batman-adv: multiple mesh clouds
Simon Wunderlich (2): Staging: batman-adv: Count Ethernet header for incoming packets Staging: batman-adv: move queue counters into bat_priv
Sven Eckelmann (14): Revert: "Staging: batman-adv: Adding netfilter-bridge hooks" Staging: batman-adv: Remove CHANGELOG Staging: batman-adv: Start new development cycle Staging: batman-adv: Calculate hamming weight using optimized kernel functions Staging: batman-adv: Directly prepare icmp packets in socket buffer Staging: batman-adv: Keep header writable and unshared Staging: batman-adv: Only clone skb data for multiple broadcasts Staging: batman-adv: Aggregate batman packets directly in skb Staging: batman-adv: Prepare vis packets directly inside a skb Staging: batman-adv: Create copy of skb with pre-allocated headroom Staging: batman-adv: Provide full headers and packets as linear skb Staging: batman-adv: Remove duplicate of attached device name Staging: batman-adv: Don't inform about dropped packets in nodebug Staging: batman-adv: Update mtu of bat device by changing mtu of slave device
drivers/staging/batman-adv/CHANGELOG | 63 --- drivers/staging/batman-adv/Makefile | 2 +- drivers/staging/batman-adv/README | 45 +-- drivers/staging/batman-adv/TODO | 3 - drivers/staging/batman-adv/aggregation.c | 57 ++-- drivers/staging/batman-adv/bat_sysfs.c | 106 ++++-- drivers/staging/batman-adv/bitarray.c | 22 +- drivers/staging/batman-adv/bitarray.h | 7 +- drivers/staging/batman-adv/hard-interface.c | 237 +++++++----- drivers/staging/batman-adv/hard-interface.h | 6 +- drivers/staging/batman-adv/hash.c | 6 +- drivers/staging/batman-adv/hash.h | 4 +- drivers/staging/batman-adv/icmp_socket.c | 70 ++-- drivers/staging/batman-adv/main.c | 138 ++----- drivers/staging/batman-adv/main.h | 28 +- drivers/staging/batman-adv/originator.c | 166 +++++---- drivers/staging/batman-adv/originator.h | 8 +- drivers/staging/batman-adv/packet.h | 26 +- drivers/staging/batman-adv/routing.c | 440 ++++++++++++--------- drivers/staging/batman-adv/routing.h | 16 +- drivers/staging/batman-adv/send.c | 174 ++++----- drivers/staging/batman-adv/send.h | 7 +- drivers/staging/batman-adv/soft-interface.c | 238 +++++++----- drivers/staging/batman-adv/soft-interface.h | 13 +- drivers/staging/batman-adv/translation-table.c | 266 +++++++------ drivers/staging/batman-adv/translation-table.h | 30 +- drivers/staging/batman-adv/types.h | 98 ++++- drivers/staging/batman-adv/unicast.c | 265 +++++++++++++ drivers/staging/batman-adv/unicast.h | 39 ++ drivers/staging/batman-adv/vis.c | 500 ++++++++++++++---------- drivers/staging/batman-adv/vis.h | 27 +-- 31 files changed, 1822 insertions(+), 1285 deletions(-)
This reverts commit 96d592ed599434d2d5f339a1d282871bc6377d2c.
The netfilter hook seems to be misused and may leak skbs in situations when NF_HOOK returns NF_STOLEN. It may not filter everything as expected. Also the ethernet bridge tables are not yet capable to understand batman-adv packet correctly.
It was only added for testing purposes and can be removed again.
Reported-by: Vasiliy Kulikov segooon@gmail.com Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/hard-interface.c | 13 ------------- drivers/staging/batman-adv/send.c | 8 ++------ 2 files changed, 2 insertions(+), 19 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index baa8b05..6e973a7 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -30,7 +30,6 @@ #include "hash.h"
#include <linux/if_arp.h> -#include <linux/netfilter_bridge.h>
#define MIN(x, y) ((x) < (y) ? (x) : (y))
@@ -431,11 +430,6 @@ out: return NOTIFY_DONE; }
-static int batman_skb_recv_finish(struct sk_buff *skb) -{ - return NF_ACCEPT; -} - /* receive a packet with the batman ethertype coming on a hard * interface */ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, @@ -456,13 +450,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (atomic_read(&module_state) != MODULE_ACTIVE) goto err_free;
- /* if netfilter/ebtables wants to block incoming batman - * packets then give them a chance to do so here */ - ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL, - batman_skb_recv_finish); - if (ret != 1) - goto err_out; - /* packet should hold at least type and version */ if (unlikely(skb_headlen(skb) < 2)) goto err_free; diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 055edee..da3c82e 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -29,7 +29,6 @@ #include "vis.h" #include "aggregation.h"
-#include <linux/netfilter_bridge.h>
static void send_outstanding_bcast_packet(struct work_struct *work);
@@ -92,12 +91,9 @@ int send_skb_packet(struct sk_buff *skb,
/* dev_queue_xmit() returns a negative result on error. However on * congestion and traffic shaping, it drops and returns NET_XMIT_DROP - * (which is > 0). This will not be treated as an error. - * Also, if netfilter/ebtables wants to block outgoing batman - * packets then giving them a chance to do so here */ + * (which is > 0). This will not be treated as an error. */
- return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, - dev_queue_xmit); + return dev_queue_xmit(skb); send_skb_err: kfree_skb(skb); return NET_XMIT_DROP;
The changelog is only generated on standalone releases. Thus it has no real value for the in-kernel version of batman-adv.
Reported-by: Abraham Arce abraham.arce.moreno@gmail.com Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/CHANGELOG | 63 ---------------------------------- 1 files changed, 0 insertions(+), 63 deletions(-) delete mode 100644 drivers/staging/batman-adv/CHANGELOG
diff --git a/drivers/staging/batman-adv/CHANGELOG b/drivers/staging/batman-adv/CHANGELOG deleted file mode 100644 index 86450b4..0000000 --- a/drivers/staging/batman-adv/CHANGELOG +++ /dev/null @@ -1,63 +0,0 @@ -batman-adv 2010.0.0: - -* support latest kernels (2.6.21 - 2.6.35) -* further code refactoring and cleaning for coding style -* move from procfs based configuration to sysfs -* reorganized sequence number handling -* limit queue lengths for batman and broadcast packets -* many bugs (endless loop and rogue packets on shutdown, wrong tcpdump output, - missing frees in error situations, sleeps in atomic contexts) squashed - - -- Fri, 18 Jun 2010 21:34:26 +0200 - -batman-adv 0.2.1: - -* support latest kernels (2.6.20 - 2.6.33) -* receive packets directly using skbs, remove old sockets and threads -* fix various regressions in the vis server -* don't disable interrupts while sending -* replace internal logging mechanism with standard kernel logging -* move vis formats into userland, one general format remains in the kernel -* allow MAC address to be set, correctly initialize them -* code refactoring and cleaning for coding style -* many bugs (null pointers, locking, hash iterators) squashed - - -- Sun, 21 Mar 2010 20:46:47 +0100 - -batman-adv 0.2: - -* support latest kernels (2.6.20 - 2.6.31) -* temporary routing loops / TTL code bug / ghost entries in originator table fixed -* internal packet queue for packet aggregation & transmission retry (ARQ) - for payload broadcasts added -* interface detection converted to event based handling to avoid timers -* major linux coding style adjustments applied -* all kernel version compatibility functions has been moved to compat.h -* use random ethernet address generator from the kernel -* /sys/module/batman_adv/version to export kernel module version -* vis: secondary interface export for dot draw format + JSON output format added -* many bugs (alignment issues, race conditions, deadlocks, etc) squashed - - -- Sat, 07 Nov 2009 15:44:31 +0100 - -batman-adv 0.1: - -* support latest kernels (2.6.20 - 2.6.28) -* LOTS of cleanup: locking, stack usage, memory leaks -* Change Ethertype from 0x0842 to 0x4305 - unregistered at IEEE, if you want to sponsor an official Ethertype ($2500) - please contact us - - -- Sun, 28 Dec 2008 00:44:31 +0100 - -batman-adv 0.1-beta: - -* layer 2 meshing based on BATMAN TQ algorithm in kernelland -* operates on any ethernet like interface -* supports IPv4, IPv6, DHCP, etc -* is controlled via /proc/net/batman-adv/ -* bridging via brctl is supported -* interface watchdog (interfaces can be (de)activated dynamically) -* offers integrated vis server which meshes/syncs with other vis servers in range - - -- Mon, 05 May 2008 14:10:04 +0200
Version 2010.1.0 of the extra kernel module was released and thus the documentation should be updated and everything prepared for the the upcoming patchset.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/README | 45 ++++++++++++++++++------------------- drivers/staging/batman-adv/main.h | 2 +- 2 files changed, 23 insertions(+), 24 deletions(-)
diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README index 7192b7f..3a975fc 100644 --- a/drivers/staging/batman-adv/README +++ b/drivers/staging/batman-adv/README @@ -1,4 +1,4 @@ -[state: 12-06-2010] +[state: 04-09-2010]
BATMAN-ADV ---------- @@ -67,15 +67,21 @@ All mesh wide settings can be found in batman's own interface folder:
# ls /sys/class/net/bat0/mesh/ -# aggregate_ogm originators transtable_global vis_mode -# orig_interval transtable_local vis_data +# aggregated_ogms bonding orig_interval vis_mode + + +There is a special folder for debugging informations: + +# ls /sys/kernel/debug/batman_adv/bat0/ +# originators socket transtable_global transtable_local +# vis_data
Some of the files contain all sort of status information regard- ing the mesh network. For example, you can view the table of originators (mesh participants) with:
-# cat /sys/class/net/bat0/mesh/originators +# cat /sys/kernel/debug/batman_adv/bat0/originators
Other files allow to change batman's behaviour to better fit your requirements. For instance, you can check the current originator @@ -83,7 +89,7 @@ interval (value in milliseconds which determines how often batman sends its broadcast packets):
# cat /sys/class/net/bat0/mesh/orig_interval -# status: 1000 +# 1000
and also change its value:
@@ -137,7 +143,7 @@ at least very similar) data. When configured as server, you can get a topology snapshot of your mesh:
-# cat /sys/class/net/bat0/mesh/vis_data +# cat /sys/kernel/debug/batman_adv/bat0/vis_data
This raw output is intended to be easily parsable and convertable with other tools. Have a look at the batctl README if you want a @@ -181,32 +187,25 @@ enabled when compiling the batman-adv module. When building bat- man-adv as part of kernel, use "make menuconfig" and enable the option "B.A.T.M.A.N. debugging".
+Those additional debug messages can be accessed using a special +file in debugfs + +# cat /sys/kernel/debug/batman_adv/bat0/log + The additional debug output is by default disabled. It can be en- -abled either at kernel modules load time or during run time. To -enable debug output at module load time, add the module parameter -debug=<value>. <value> can take one of four values. +abled during run time. Following log_levels are defined:
0 - All debug output disabled 1 - Enable messages related to routing / flooding / broadcasting 2 - Enable route or hna added / changed / deleted 3 - Enable all messages
-e.g. +The debug output can be changed at runtime using the file +/sys/class/net/bat0/mesh/log_level. e.g.
-# modprobe batman-adv debug=2 +# echo 2 > /sys/class/net/bat0/mesh/log_level
-will load the module and enable debug messages for when routes or -HNAs change. - -The debug output can also be changed at runtime using the file -/sys/module/batman-adv/parameters/debug. e.g. - -# echo 2 > /sys/module/batman-adv/parameters/debug - -enables debug messages for when routes or HNAs - -The debug output is sent to the kernel logs. So try dmesg, lo- -gread, etc to see the debug messages. +will enable debug messages for when routes or HNAs change.
BATCTL diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 8513261..9b30eef 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -30,7 +30,7 @@ #define DRIVER_DESC "B.A.T.M.A.N. advanced" #define DRIVER_DEVICE "batman-adv"
-#define SOURCE_VERSION "maint" +#define SOURCE_VERSION "next"
/* B.A.T.M.A.N. parameters */
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
The Ethernet header is counted when transmitting a packet, so it should also be counted when receiving a packet. With this patch, the rx_bytes and tx_bytes statistics behave like an ordinary Ethernet interface.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/soft-interface.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 2ea97de..6f22e6e 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -259,7 +259,7 @@ void interface_rx(struct sk_buff *skb, int hdr_size) * PACKET_OTHERHOST or PACKET_HOST */
priv->stats.rx_packets++; - priv->stats.rx_bytes += skb->len; + priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
dev->last_rx = jiffies;
The Kernighan algorithm is not able to calculate the number of set bits in parallel and the compiler cannot replace it with optimized instructions.
The kernel provides specialised functions for each cpu which can either use a software implementation or hardware instruction depending on the target cpu.
Reported-by: David S. Miller davem@davemloft.net Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/TODO | 1 - drivers/staging/batman-adv/bitarray.c | 15 +++++---------- drivers/staging/batman-adv/bitarray.h | 3 ++- 3 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index 9c5aea2..d8bf845 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -1,4 +1,3 @@ - * Use hweight* for hamming weight calculation * Save/cache packets direktly as skb instead of using a normal memory region and copying it in a skb using send_raw_packet and similar functions * Request a new review diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c index dd4193c..9dbaf1e 100644 --- a/drivers/staging/batman-adv/bitarray.c +++ b/drivers/staging/batman-adv/bitarray.c @@ -22,6 +22,8 @@ #include "main.h" #include "bitarray.h"
+#include <linux/bitops.h> + /* returns true if the corresponding bit in the given seq_bits indicates true * and curr_seqno is within range of last_seqno */ uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno, @@ -187,21 +189,14 @@ char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff, }
/* count the hamming weight, how many good packets did we receive? just count - * the 1's. The inner loop uses the Kernighan algorithm, see - * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan + * the 1's. */ int bit_packet_count(TYPE_OF_WORD *seq_bits) { int i, hamming = 0; - TYPE_OF_WORD word;
- for (i = 0; i < NUM_WORDS; i++) { - word = seq_bits[i]; + for (i = 0; i < NUM_WORDS; i++) + hamming += hweight_long(seq_bits[i]);
- while (word) { - word &= word-1; - hamming++; - } - } return hamming; } diff --git a/drivers/staging/batman-adv/bitarray.h b/drivers/staging/batman-adv/bitarray.h index 01897d6..c0c1730 100644 --- a/drivers/staging/batman-adv/bitarray.h +++ b/drivers/staging/batman-adv/bitarray.h @@ -22,7 +22,8 @@ #ifndef _NET_BATMAN_ADV_BITARRAY_H_ #define _NET_BATMAN_ADV_BITARRAY_H_
-/* you should choose something big, if you don't want to waste cpu */ +/* you should choose something big, if you don't want to waste cpu + * and keep the type in sync with bit_packet_count */ #define TYPE_OF_WORD unsigned long #define WORD_BIT_SIZE (sizeof(TYPE_OF_WORD) * 8)
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
to support multiple mesh devices later, we need to move global variables like the queues into corresponding private structs bat_priv of the soft devices.
Note that this patch still has a lot of FIXMEs and depends on the global soft_device variable. This should be resolved later, e.g. by referencing the parent soft device in batman_if.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/aggregation.c | 6 +++--- drivers/staging/batman-adv/bat_sysfs.c | 2 ++ drivers/staging/batman-adv/main.c | 6 ------ drivers/staging/batman-adv/main.h | 2 -- drivers/staging/batman-adv/send.c | 12 ++++++++---- drivers/staging/batman-adv/types.h | 2 ++ 6 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c index 9862d16..d738b7a 100644 --- a/drivers/staging/batman-adv/aggregation.c +++ b/drivers/staging/batman-adv/aggregation.c @@ -111,7 +111,7 @@ static void new_aggregated_packet(unsigned char *packet_buff,
/* own packet should always be scheduled */ if (!own_packet) { - if (!atomic_dec_not_zero(&batman_queue_left)) { + if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { bat_dbg(DBG_BATMAN, bat_priv, "batman packet queue full\n"); return; @@ -121,7 +121,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); if (!forw_packet_aggr) { if (!own_packet) - atomic_inc(&batman_queue_left); + atomic_inc(&bat_priv->batman_queue_left); return; }
@@ -129,7 +129,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, GFP_ATOMIC); if (!forw_packet_aggr->packet_buff) { if (!own_packet) - atomic_inc(&batman_queue_left); + atomic_inc(&bat_priv->batman_queue_left); kfree(forw_packet_aggr); return; } diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index 05ca15a..d49adde 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -311,6 +311,8 @@ int sysfs_add_meshif(struct net_device *dev) atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->orig_interval, 1000); atomic_set(&bat_priv->log_level, 0); + atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN); + atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0; diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index ef7c20a..c0a3373 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -42,9 +42,6 @@ DEFINE_SPINLOCK(orig_hash_lock); DEFINE_SPINLOCK(forw_bat_list_lock); DEFINE_SPINLOCK(forw_bcast_list_lock);
-atomic_t bcast_queue_left; -atomic_t batman_queue_left; - int16_t num_hna;
struct net_device *soft_device; @@ -69,9 +66,6 @@ static int __init batman_init(void)
atomic_set(&module_state, MODULE_INACTIVE);
- atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN); - atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN); - /* the name should not be longer than 10 chars - see * http://lwn.net/Articles/23634/ */ bat_event_workqueue = create_singlethread_workqueue("bat_events"); diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 9b30eef..2d364e0 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -136,8 +136,6 @@ extern spinlock_t orig_hash_lock; extern spinlock_t forw_bat_list_lock; extern spinlock_t forw_bcast_list_lock;
-extern atomic_t bcast_queue_left; -extern atomic_t batman_queue_left; extern int16_t num_hna;
extern struct net_device *soft_device; diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index da3c82e..e874cae 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -404,7 +404,7 @@ int add_bcast_packet_to_list(struct sk_buff *skb) /* FIXME: each batman_if will be attached to a softif */ struct bat_priv *bat_priv = netdev_priv(soft_device);
- if (!atomic_dec_not_zero(&bcast_queue_left)) { + if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) { bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n"); goto out; } @@ -436,7 +436,7 @@ int add_bcast_packet_to_list(struct sk_buff *skb) packet_free: kfree(forw_packet); out_and_inc: - atomic_inc(&bcast_queue_left); + atomic_inc(&bat_priv->bcast_queue_left); out: return NETDEV_TX_BUSY; } @@ -450,6 +450,8 @@ static void send_outstanding_bcast_packet(struct work_struct *work) container_of(delayed_work, struct forw_packet, delayed_work); unsigned long flags; struct sk_buff *skb1; + /* FIXME: each batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device);
spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_del(&forw_packet->list); @@ -479,7 +481,7 @@ static void send_outstanding_bcast_packet(struct work_struct *work)
out: forw_packet_free(forw_packet); - atomic_inc(&bcast_queue_left); + atomic_inc(&bat_priv->bcast_queue_left); }
void send_outstanding_bat_packet(struct work_struct *work) @@ -489,6 +491,8 @@ void send_outstanding_bat_packet(struct work_struct *work) struct forw_packet *forw_packet = container_of(delayed_work, struct forw_packet, delayed_work); unsigned long flags; + /* FIXME: each batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device);
spin_lock_irqsave(&forw_bat_list_lock, flags); hlist_del(&forw_packet->list); @@ -510,7 +514,7 @@ void send_outstanding_bat_packet(struct work_struct *work) out: /* don't count own packet */ if (!forw_packet->own) - atomic_inc(&batman_queue_left); + atomic_inc(&bat_priv->batman_queue_left);
forw_packet_free(forw_packet); } diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 9aa9d36..67bf4db 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -113,6 +113,8 @@ struct bat_priv { atomic_t vis_mode; atomic_t orig_interval; atomic_t log_level; + atomic_t bcast_queue_left; + atomic_t batman_queue_left; char num_ifaces; struct debug_log *debug_log; struct batman_if *primary_if;
From: Marek Lindner lindner_marek@yahoo.de
Signed-off-by: Marek Lindner lindner_marek@yahoo.de [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/Makefile | 2 +- drivers/staging/batman-adv/soft-interface.c | 74 ++++------------------- drivers/staging/batman-adv/unicast.c | 87 +++++++++++++++++++++++++++ drivers/staging/batman-adv/unicast.h | 27 ++++++++ 4 files changed, 128 insertions(+), 62 deletions(-) create mode 100644 drivers/staging/batman-adv/unicast.c create mode 100644 drivers/staging/batman-adv/unicast.h
diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile index e9817b5..4b5c434 100644 --- a/drivers/staging/batman-adv/Makefile +++ b/drivers/staging/batman-adv/Makefile @@ -19,4 +19,4 @@ #
obj-$(CONFIG_BATMAN_ADV) += batman-adv.o -batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o +batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o unicast.o diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 6f22e6e..315fdeb 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -22,14 +22,12 @@ #include "main.h" #include "soft-interface.h" #include "hard-interface.h" -#include "routing.h" -#include "send.h" #include "translation-table.h" -#include "types.h" -#include "hash.h" +#include "send.h" #include <linux/slab.h> #include <linux/ethtool.h> #include <linux/etherdevice.h> +#include "unicast.h"
static uint32_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid * broadcast storms */ @@ -127,24 +125,14 @@ static int interface_change_mtu(struct net_device *dev, int new_mtu)
int interface_tx(struct sk_buff *skb, struct net_device *dev) { - struct unicast_packet *unicast_packet; - struct bcast_packet *bcast_packet; - struct orig_node *orig_node; - struct neigh_node *router; struct ethhdr *ethhdr = (struct ethhdr *)skb->data; - struct bat_priv *priv = netdev_priv(dev); - struct batman_if *batman_if; - struct bat_priv *bat_priv; - uint8_t dstaddr[6]; - int data_len = skb->len; - unsigned long flags; + struct bat_priv *bat_priv = netdev_priv(dev); + struct bcast_packet *bcast_packet; + int data_len = skb->len, ret;
if (atomic_read(&module_state) != MODULE_ACTIVE) goto dropped;
- /* FIXME: each batman_if will be attached to a softif */ - bat_priv = netdev_priv(soft_device); - dev->trans_start = jiffies; /* TODO: check this for locks */ hna_local_add(ethhdr->h_source); @@ -179,55 +167,19 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
/* unicast packet */ } else { - spin_lock_irqsave(&orig_hash_lock, flags); - /* get routing information */ - orig_node = ((struct orig_node *)hash_find(orig_hash, - ethhdr->h_dest)); - - /* check for hna host */ - if (!orig_node) - orig_node = transtable_search(ethhdr->h_dest); - - router = find_router(orig_node, NULL); - - if (!router) - goto unlock; - - /* don't lock while sending the packets ... we therefore - * copy the required data before sending */ - - batman_if = router->if_incoming; - memcpy(dstaddr, router->addr, ETH_ALEN); - - spin_unlock_irqrestore(&orig_hash_lock, flags); - - if (batman_if->if_status != IF_ACTIVE) - goto dropped; - - if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) - goto dropped; - - unicast_packet = (struct unicast_packet *)skb->data; - - unicast_packet->version = COMPAT_VERSION; - /* batman packet type: unicast */ - unicast_packet->packet_type = BAT_UNICAST; - /* set unicast ttl */ - unicast_packet->ttl = TTL; - /* copy the destination for faster routing */ - memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); - - send_skb_packet(skb, batman_if, dstaddr); + ret = unicast_send_skb(skb, bat_priv); + if (ret != 0) { + bat_priv->stats.tx_dropped++; + goto end; + } }
- priv->stats.tx_packets++; - priv->stats.tx_bytes += data_len; + bat_priv->stats.tx_packets++; + bat_priv->stats.tx_bytes += data_len; goto end;
-unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); dropped: - priv->stats.tx_dropped++; + bat_priv->stats.tx_dropped++; kfree_skb(skb); end: return NETDEV_TX_OK; diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c new file mode 100644 index 0000000..27c4abb --- /dev/null +++ b/drivers/staging/batman-adv/unicast.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Andreas Langer + * + * 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 "unicast.h" +#include "send.h" +#include "soft-interface.h" +#include "hash.h" +#include "translation-table.h" +#include "routing.h" +#include "hard-interface.h" + +int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) +{ + struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct unicast_packet *unicast_packet; + struct orig_node *orig_node; + struct batman_if *batman_if; + struct neigh_node *router; + uint8_t dstaddr[6]; + unsigned long flags; + + spin_lock_irqsave(&orig_hash_lock, flags); + + /* get routing information */ + orig_node = ((struct orig_node *)hash_find(orig_hash, ethhdr->h_dest)); + + /* check for hna host */ + if (!orig_node) + orig_node = transtable_search(ethhdr->h_dest); + + router = find_router(orig_node, NULL); + + if (!router) + goto unlock; + + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + + batman_if = router->if_incoming; + memcpy(dstaddr, router->addr, ETH_ALEN); + + spin_unlock_irqrestore(&orig_hash_lock, flags); + + if (batman_if->if_status != IF_ACTIVE) + goto dropped; + + if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) + goto dropped; + + unicast_packet = (struct unicast_packet *)skb->data; + + unicast_packet->version = COMPAT_VERSION; + /* batman packet type: unicast */ + unicast_packet->packet_type = BAT_UNICAST; + /* set unicast ttl */ + unicast_packet->ttl = TTL; + /* copy the destination for faster routing */ + memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); + + send_skb_packet(skb, batman_if, dstaddr); + return 0; + +unlock: + spin_unlock_irqrestore(&orig_hash_lock, flags); +dropped: + kfree_skb(skb); + return 1; +} diff --git a/drivers/staging/batman-adv/unicast.h b/drivers/staging/batman-adv/unicast.h new file mode 100644 index 0000000..dd00703 --- /dev/null +++ b/drivers/staging/batman-adv/unicast.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 B.A.T.M.A.N. contributors: + * + * Andreas Langer + * + * 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 + * + */ + +#ifndef _NET_BATMAN_ADV_UNICAST_H_ +#define _NET_BATMAN_ADV_UNICAST_H_ + +int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv); + +#endif /* _NET_BATMAN_ADV_UNICAST_H_ */
From: Andreas Langer an.langer@gmx.de
This patch implements a simple layer2 fragmentation to allow traffic exchange over network interfaces with a MTU smaller than 1500 bytes. The fragmentation splits the big packets into two parts and marks the frames accordingly. The receiving end buffers the packets to reassemble the orignal packet before passing it to the higher layers. This feature makes it necessary to modify the batman-adv encapsulation for unicast packets by adding a sequence number, flags and the originator address. This modifcation is part of a seperate packet type for fragemented packets to keep the original overhead as low as possible. This patch enables the feature by default to ensure the data traffic can travel through the network. But it also prints a warning to notify the user about the performance implications.
Note: Fragmentation should be avoided at all costs since it has a dramatic impact on the performance, especially when it comes wifi networks. Instead of a single packet, 2 packets have to be sent! Not only valuable airtime is wasted but also packetloss decreases the throughput. A link with 50% packetloss and fragmentation enabled is pretty much unusable.
Signed-off-by: Andreas Langer an.langer@gmx.de [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/bat_sysfs.c | 55 ++++++++ drivers/staging/batman-adv/hard-interface.c | 34 +++++- drivers/staging/batman-adv/originator.c | 10 ++ drivers/staging/batman-adv/packet.h | 26 +++- drivers/staging/batman-adv/routing.c | 115 ++++++++++++++--- drivers/staging/batman-adv/routing.h | 1 + drivers/staging/batman-adv/soft-interface.c | 4 +- drivers/staging/batman-adv/types.h | 10 ++ drivers/staging/batman-adv/unicast.c | 177 +++++++++++++++++++++++++++ drivers/staging/batman-adv/unicast.h | 12 ++ 10 files changed, 416 insertions(+), 28 deletions(-)
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index d49adde..b9fe391 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -134,6 +134,58 @@ static ssize_t store_bond(struct kobject *kobj, struct attribute *attr, return count; }
+static ssize_t show_frag(struct kobject *kobj, struct attribute *attr, + char *buff) +{ + struct device *dev = to_dev(kobj->parent); + struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); + int frag_status = atomic_read(&bat_priv->frag_enabled); + + return sprintf(buff, "%s\n", + frag_status == 0 ? "disabled" : "enabled"); +} + +static ssize_t store_frag(struct kobject *kobj, struct attribute *attr, + char *buff, size_t count) +{ + struct device *dev = to_dev(kobj->parent); + struct net_device *net_dev = to_net_dev(dev); + struct bat_priv *bat_priv = netdev_priv(net_dev); + int frag_enabled_tmp = -1; + + if (((count == 2) && (buff[0] == '1')) || + (strncmp(buff, "enable", 6) == 0)) + frag_enabled_tmp = 1; + + if (((count == 2) && (buff[0] == '0')) || + (strncmp(buff, "disable", 7) == 0)) + frag_enabled_tmp = 0; + + if (frag_enabled_tmp < 0) { + if (buff[count - 1] == '\n') + buff[count - 1] = '\0'; + + bat_err(net_dev, + "Invalid parameter for 'fragmentation' setting on mesh" + "received: %s\n", buff); + return -EINVAL; + } + + if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp) + return count; + + bat_info(net_dev, "Changing fragmentation from: %s to: %s\n", + atomic_read(&bat_priv->frag_enabled) == 1 ? + "enabled" : "disabled", + frag_enabled_tmp == 1 ? "enabled" : "disabled"); + + atomic_set(&bat_priv->frag_enabled, (unsigned)frag_enabled_tmp); + + update_min_mtu(); + + return count; +} + static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, char *buff) { @@ -279,6 +331,7 @@ static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr, static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR, show_aggr_ogms, store_aggr_ogms); static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond); +static BAT_ATTR(fragmentation, S_IRUGO | S_IWUSR, show_frag, store_frag); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR, show_orig_interval, store_orig_interval); @@ -289,6 +342,7 @@ static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level); static struct bat_attribute *mesh_attrs[] = { &bat_attr_aggregated_ogms, &bat_attr_bonding, + &bat_attr_fragmentation, &bat_attr_vis_mode, &bat_attr_orig_interval, #ifdef CONFIG_BATMAN_ADV_DEBUG @@ -308,6 +362,7 @@ int sysfs_add_meshif(struct net_device *dev) routine as soon as we have it */ atomic_set(&bat_priv->aggregation_enabled, 1); atomic_set(&bat_priv->bonding_enabled, 0); + atomic_set(&bat_priv->frag_enabled, 1); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->orig_interval, 1000); atomic_set(&bat_priv->log_level, 0); diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 6e973a7..82d3d55 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -166,6 +166,11 @@ int hardif_min_mtu(void) /* allow big frames if all devices are capable to do so * (have MTU > 1500 + BAT_HEADER_LEN) */ int min_mtu = ETH_DATA_LEN; + /* FIXME: each batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device); + + if (atomic_read(&bat_priv->frag_enabled)) + goto out;
rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { @@ -175,7 +180,7 @@ int hardif_min_mtu(void) min_mtu); } rcu_read_unlock(); - +out: return min_mtu; }
@@ -261,8 +266,30 @@ int hardif_enable_interface(struct batman_if *batman_if) orig_hash_add_if(batman_if, bat_priv->num_ifaces);
atomic_set(&batman_if->seqno, 1); + atomic_set(&batman_if->frag_seqno, 1); bat_info(soft_device, "Adding interface: %s\n", batman_if->dev);
+ if (atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < + ETH_DATA_LEN + BAT_HEADER_LEN) + bat_info(soft_device, + "The MTU of interface %s is too small (%i) to handle " + "the transport of batman-adv packets. Packets going " + "over this interface will be fragmented on layer2 " + "which could impact the performance. Setting the MTU " + "to %zi would solve the problem.\n", + batman_if->dev, batman_if->net_dev->mtu, + ETH_DATA_LEN + BAT_HEADER_LEN); + + if (!atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < + ETH_DATA_LEN + BAT_HEADER_LEN) + bat_info(soft_device, + "The MTU of interface %s is too small (%i) to handle " + "the transport of batman-adv packets. If you experience" + " problems getting traffic through try increasing the " + "MTU to %zi.\n", + batman_if->dev, batman_if->net_dev->mtu, + ETH_DATA_LEN + BAT_HEADER_LEN); + if (hardif_is_iface_up(batman_if)) hardif_activate_interface(soft_device, bat_priv, batman_if); else @@ -495,6 +522,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, ret = recv_unicast_packet(skb, batman_if); break;
+ /* fragmented unicast packet */ + case BAT_UNICAST_FRAG: + ret = recv_ucast_frag_packet(skb, batman_if); + break; + /* broadcast packet */ case BAT_BCAST: ret = recv_bcast_packet(skb); diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index de5a8c1..b51a13e 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -27,6 +27,7 @@ #include "translation-table.h" #include "routing.h" #include "hard-interface.h" +#include "unicast.h"
static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
@@ -95,6 +96,7 @@ static void free_orig_node(void *data) kfree(neigh_node); }
+ frag_list_free(&orig_node->frag_list); hna_global_del_orig(orig_node, "originator timed out");
kfree(orig_node->bcast_own); @@ -157,6 +159,10 @@ struct orig_node *get_orig_node(uint8_t *addr)
size = bat_priv->num_ifaces * sizeof(uint8_t); orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); + + INIT_LIST_HEAD(&orig_node->frag_list); + orig_node->last_frag_packet = 0; + if (!orig_node->bcast_own_sum) goto free_bcast_own;
@@ -271,6 +277,10 @@ void purge_orig(struct work_struct *work) hash_remove_bucket(orig_hash, &hashit); free_orig_node(orig_node); } + + if (time_after(jiffies, (orig_node->last_frag_packet + + msecs_to_jiffies(FRAG_TIMEOUT)))) + frag_list_free(&orig_node->frag_list); }
spin_unlock_irqrestore(&orig_hash_lock, flags); diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h index abb5e46..44de1bf 100644 --- a/drivers/staging/batman-adv/packet.h +++ b/drivers/staging/batman-adv/packet.h @@ -24,14 +24,15 @@
#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
-#define BAT_PACKET 0x01 -#define BAT_ICMP 0x02 -#define BAT_UNICAST 0x03 -#define BAT_BCAST 0x04 -#define BAT_VIS 0x05 +#define BAT_PACKET 0x01 +#define BAT_ICMP 0x02 +#define BAT_UNICAST 0x03 +#define BAT_BCAST 0x04 +#define BAT_VIS 0x05 +#define BAT_UNICAST_FRAG 0x06
/* this file is included by batctl which needs these defines */ -#define COMPAT_VERSION 11 +#define COMPAT_VERSION 13 #define DIRECTLINK 0x40 #define VIS_SERVER 0x20 #define PRIMARIES_FIRST_HOP 0x10 @@ -47,6 +48,9 @@ #define VIS_TYPE_SERVER_SYNC 0 #define VIS_TYPE_CLIENT_UPDATE 1
+/* fragmentation defines */ +#define UNI_FRAG_HEAD 0x01 + struct batman_packet { uint8_t packet_type; uint8_t version; /* batman version field */ @@ -96,6 +100,16 @@ struct unicast_packet { uint8_t ttl; } __attribute__((packed));
+struct unicast_frag_packet { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t dest[6]; + uint8_t ttl; + uint8_t flags; + uint8_t orig[6]; + uint16_t seqno; +} __attribute__((packed)); + struct bcast_packet { uint8_t packet_type; uint8_t version; /* batman version field */ diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 032195e..d8e77ac 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -32,6 +32,7 @@ #include "ring_buffer.h" #include "vis.h" #include "aggregation.h" +#include "unicast.h"
static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
@@ -1105,43 +1106,43 @@ struct neigh_node *find_router(struct orig_node *orig_node, return router; }
-int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) +static int check_unicast_packet(struct sk_buff *skb, int hdr_size) { - struct unicast_packet *unicast_packet; - struct orig_node *orig_node; - struct neigh_node *router; struct ethhdr *ethhdr; - struct batman_if *batman_if; - struct sk_buff *skb_old; - uint8_t dstaddr[ETH_ALEN]; - int hdr_size = sizeof(struct unicast_packet); - unsigned long flags;
/* drop packet if it has not necessary minimum size */ if (skb_headlen(skb) < hdr_size) - return NET_RX_DROP; + return -1;
ethhdr = (struct ethhdr *) skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */ if (is_bcast(ethhdr->h_dest)) - return NET_RX_DROP; + return -1;
/* packet with broadcast sender address */ if (is_bcast(ethhdr->h_source)) - return NET_RX_DROP; + return -1;
/* not for me */ if (!is_my_mac(ethhdr->h_dest)) - return NET_RX_DROP; + return -1;
- unicast_packet = (struct unicast_packet *) skb->data; + return 0; +}
- /* packet for me */ - if (is_my_mac(unicast_packet->dest)) { - interface_rx(skb, hdr_size); - return NET_RX_SUCCESS; - } +static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, + int hdr_size) +{ + struct orig_node *orig_node; + struct neigh_node *router; + struct batman_if *batman_if; + struct sk_buff *skb_old; + uint8_t dstaddr[ETH_ALEN]; + unsigned long flags; + struct unicast_packet *unicast_packet = + (struct unicast_packet *) skb->data; + struct ethhdr *ethhdr = (struct ethhdr *) skb_mac_header(skb);
/* TTL exceeded */ if (unicast_packet->ttl < 2) { @@ -1172,7 +1173,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) { + if (!skb_clone_writable(skb, hdr_size)) { skb_old = skb; skb = skb_copy(skb, GFP_ATOMIC); if (!skb) @@ -1191,6 +1192,80 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) return NET_RX_SUCCESS; }
+int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) +{ + struct unicast_packet *unicast_packet; + int hdr_size = sizeof(struct unicast_packet); + + if (check_unicast_packet(skb, hdr_size) < 0) + return NET_RX_DROP; + + unicast_packet = (struct unicast_packet *) skb->data; + + /* packet for me */ + if (is_my_mac(unicast_packet->dest)) { + interface_rx(skb, hdr_size); + return NET_RX_SUCCESS; + } + + return route_unicast_packet(skb, recv_if, hdr_size); +} + +int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) +{ + struct unicast_frag_packet *unicast_packet; + struct orig_node *orig_node; + struct frag_packet_list_entry *tmp_frag_entry; + int hdr_size = sizeof(struct unicast_frag_packet); + unsigned long flags; + + if (check_unicast_packet(skb, hdr_size) < 0) + return NET_RX_DROP; + + unicast_packet = (struct unicast_frag_packet *) skb->data; + + /* packet for me */ + if (is_my_mac(unicast_packet->dest)) { + + spin_lock_irqsave(&orig_hash_lock, flags); + orig_node = ((struct orig_node *) + hash_find(orig_hash, unicast_packet->orig)); + + if (!orig_node) { + pr_warning("couldn't find orig node for " + "fragmentation\n"); + spin_unlock_irqrestore(&orig_hash_lock, flags); + return NET_RX_DROP; + } + + orig_node->last_frag_packet = jiffies; + + if (list_empty(&orig_node->frag_list)) + create_frag_buffer(&orig_node->frag_list); + + tmp_frag_entry = + search_frag_packet(&orig_node->frag_list, + unicast_packet); + + if (!tmp_frag_entry) { + create_frag_entry(&orig_node->frag_list, skb); + spin_unlock_irqrestore(&orig_hash_lock, flags); + return NET_RX_SUCCESS; + } + + skb = merge_frag_packet(&orig_node->frag_list, + tmp_frag_entry, skb); + spin_unlock_irqrestore(&orig_hash_lock, flags); + if (!skb) + return NET_RX_DROP; + + interface_rx(skb, hdr_size); + return NET_RX_SUCCESS; + } + + return route_unicast_packet(skb, recv_if, hdr_size); +} + int recv_bcast_packet(struct sk_buff *skb) { struct orig_node *orig_node; diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 3eac64e..81c684f 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -34,6 +34,7 @@ void update_routes(struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); int recv_icmp_packet(struct sk_buff *skb); int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); +int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bcast_packet(struct sk_buff *skb); int recv_vis_packet(struct sk_buff *skb); int recv_bat_packet(struct sk_buff *skb, diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 315fdeb..d60b1a8 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -249,7 +249,9 @@ void interface_setup(struct net_device *dev) #endif dev->destructor = free_netdev;
- dev->mtu = hardif_min_mtu(); + dev->mtu = ETH_DATA_LEN; /* can't call min_mtu, because the + * needed variables have not been + * initialized yet */ dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the * skbuff for our header */
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 67bf4db..ac16575 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -41,6 +41,7 @@ struct batman_if { char addr_str[ETH_STR_LEN]; struct net_device *net_dev; atomic_t seqno; + atomic_t frag_seqno; unsigned char *packet_buff; int packet_len; struct kobject *hardif_obj; @@ -81,6 +82,8 @@ struct orig_node { TYPE_OF_WORD bcast_bits[NUM_WORDS]; uint32_t last_bcast_seqno; struct list_head neigh_list; + struct list_head frag_list; + unsigned long last_frag_packet; struct { uint8_t candidates; struct neigh_node *selected; @@ -110,6 +113,7 @@ struct bat_priv { struct net_device_stats stats; atomic_t aggregation_enabled; atomic_t bonding_enabled; + atomic_t frag_enabled; atomic_t vis_mode; atomic_t orig_interval; atomic_t log_level; @@ -183,4 +187,10 @@ struct debug_log { wait_queue_head_t queue_wait; };
+struct frag_packet_list_entry { + struct list_head list; + uint16_t seqno; + struct sk_buff *skb; +}; + #endif /* _NET_BATMAN_ADV_TYPES_H_ */ diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c index 27c4abb..153914e 100644 --- a/drivers/staging/batman-adv/unicast.c +++ b/drivers/staging/batman-adv/unicast.c @@ -28,6 +28,177 @@ #include "routing.h" #include "hard-interface.h"
+ +struct sk_buff *merge_frag_packet(struct list_head *head, + struct frag_packet_list_entry *tfp, + struct sk_buff *skb) +{ + struct unicast_frag_packet *up = + (struct unicast_frag_packet *) skb->data; + struct sk_buff *tmp_skb; + + /* set skb to the first part and tmp_skb to the second part */ + if (up->flags & UNI_FRAG_HEAD) { + tmp_skb = tfp->skb; + } else { + tmp_skb = skb; + skb = tfp->skb; + } + + skb_pull(tmp_skb, sizeof(struct unicast_frag_packet)); + if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0) { + /* free buffered skb, skb will be freed later */ + kfree_skb(tfp->skb); + return NULL; + } + + /* move free entry to end */ + tfp->skb = NULL; + tfp->seqno = 0; + list_move_tail(&tfp->list, head); + + memcpy(skb_put(skb, tmp_skb->len), tmp_skb->data, tmp_skb->len); + kfree_skb(tmp_skb); + return skb; +} + +void create_frag_entry(struct list_head *head, struct sk_buff *skb) +{ + struct frag_packet_list_entry *tfp; + struct unicast_frag_packet *up = + (struct unicast_frag_packet *) skb->data; + + /* free and oldest packets stand at the end */ + tfp = list_entry((head)->prev, typeof(*tfp), list); + kfree_skb(tfp->skb); + + tfp->seqno = ntohs(up->seqno); + tfp->skb = skb; + list_move(&tfp->list, head); + return; +} + +void create_frag_buffer(struct list_head *head) +{ + int i; + struct frag_packet_list_entry *tfp; + + for (i = 0; i < FRAG_BUFFER_SIZE; i++) { + tfp = kmalloc(sizeof(struct frag_packet_list_entry), + GFP_ATOMIC); + tfp->skb = NULL; + tfp->seqno = 0; + INIT_LIST_HEAD(&tfp->list); + list_add(&tfp->list, head); + } + + return; +} + +struct frag_packet_list_entry *search_frag_packet(struct list_head *head, + struct unicast_frag_packet *up) +{ + struct frag_packet_list_entry *tfp; + struct unicast_frag_packet *tmp_up = NULL; + uint16_t search_seqno; + + if (up->flags & UNI_FRAG_HEAD) + search_seqno = ntohs(up->seqno)+1; + else + search_seqno = ntohs(up->seqno)-1; + + list_for_each_entry(tfp, head, list) { + + if (!tfp->skb) + continue; + + if (tfp->seqno == ntohs(up->seqno)) + goto mov_tail; + + tmp_up = (struct unicast_frag_packet *) tfp->skb->data; + + if (tfp->seqno == search_seqno) { + + if ((tmp_up->flags & UNI_FRAG_HEAD) != + (up->flags & UNI_FRAG_HEAD)) + return tfp; + else + goto mov_tail; + } + } + return NULL; + +mov_tail: + list_move_tail(&tfp->list, head); + return NULL; +} + +void frag_list_free(struct list_head *head) +{ + struct frag_packet_list_entry *pf, *tmp_pf; + + if (!list_empty(head)) { + + list_for_each_entry_safe(pf, tmp_pf, head, list) { + kfree_skb(pf->skb); + list_del(&pf->list); + kfree(pf); + } + } + return; +} + +static int unicast_send_frag_skb(struct sk_buff *skb, struct bat_priv *bat_priv, + struct batman_if *batman_if, uint8_t dstaddr[], + struct orig_node *orig_node) +{ + struct unicast_frag_packet *ucast_frag1, *ucast_frag2; + int hdr_len = sizeof(struct unicast_frag_packet); + struct sk_buff *frag_skb; + int data_len = skb->len; + + if (!bat_priv->primary_if) + goto dropped; + + frag_skb = dev_alloc_skb(data_len - (data_len / 2) + hdr_len); + skb_split(skb, frag_skb, data_len / 2); + + if (my_skb_push(frag_skb, hdr_len) < 0 || + my_skb_push(skb, hdr_len) < 0) + goto drop_frag; + + ucast_frag1 = (struct unicast_frag_packet *)skb->data; + ucast_frag2 = (struct unicast_frag_packet *)frag_skb->data; + + ucast_frag1->version = COMPAT_VERSION; + ucast_frag1->packet_type = BAT_UNICAST_FRAG; + ucast_frag1->ttl = TTL; + memcpy(ucast_frag1->orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(ucast_frag1->dest, orig_node->orig, ETH_ALEN); + + memcpy(ucast_frag2, ucast_frag1, sizeof(struct unicast_frag_packet)); + + ucast_frag1->flags |= UNI_FRAG_HEAD; + ucast_frag2->flags &= ~UNI_FRAG_HEAD; + + ucast_frag1->seqno = htons((uint16_t)atomic_inc_return( + &batman_if->frag_seqno)); + + ucast_frag2->seqno = htons((uint16_t)atomic_inc_return( + &batman_if->frag_seqno)); + + send_skb_packet(skb, batman_if, dstaddr); + send_skb_packet(frag_skb, batman_if, dstaddr); + return 0; + +drop_frag: + kfree_skb(frag_skb); +dropped: + kfree_skb(skb); + return 1; +} + int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) { struct ethhdr *ethhdr = (struct ethhdr *)skb->data; @@ -35,6 +206,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) struct orig_node *orig_node; struct batman_if *batman_if; struct neigh_node *router; + int data_len = skb->len; uint8_t dstaddr[6]; unsigned long flags;
@@ -63,6 +235,11 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) if (batman_if->if_status != IF_ACTIVE) goto dropped;
+ if (atomic_read(&bat_priv->frag_enabled) && + data_len + sizeof(struct unicast_packet) > batman_if->net_dev->mtu) + return unicast_send_frag_skb(skb, bat_priv, batman_if, + dstaddr, orig_node); + if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) goto dropped;
diff --git a/drivers/staging/batman-adv/unicast.h b/drivers/staging/batman-adv/unicast.h index dd00703..1d5cbeb 100644 --- a/drivers/staging/batman-adv/unicast.h +++ b/drivers/staging/batman-adv/unicast.h @@ -22,6 +22,18 @@ #ifndef _NET_BATMAN_ADV_UNICAST_H_ #define _NET_BATMAN_ADV_UNICAST_H_
+#define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */ +#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ + +struct sk_buff *merge_frag_packet(struct list_head *head, + struct frag_packet_list_entry *tfp, + struct sk_buff *skb); + +void create_frag_entry(struct list_head *head, struct sk_buff *skb); +void create_frag_buffer(struct list_head *head); +struct frag_packet_list_entry *search_frag_packet(struct list_head *head, + struct unicast_frag_packet *up); +void frag_list_free(struct list_head *head); int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv);
#endif /* _NET_BATMAN_ADV_UNICAST_H_ */
It is unnecessary to generate an icmp packet in an extra memory region and than copying it to a new allocated skb.
This also resolved the problem that we do inform the user that we couldn't send the packet because we couldn't allocate the socket buffer.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/icmp_socket.c | 60 +++++++++++++++++++----------- 1 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index 3ae7dd2..8e986a1 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -154,7 +154,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, { struct socket_client *socket_client = file->private_data; struct bat_priv *bat_priv = socket_client->bat_priv; - struct icmp_packet_rr icmp_packet; + struct sk_buff *skb; + struct icmp_packet_rr *icmp_packet; struct orig_node *orig_node; struct batman_if *batman_if; size_t packet_len = sizeof(struct icmp_packet); @@ -174,40 +175,53 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (len >= sizeof(struct icmp_packet_rr)) packet_len = sizeof(struct icmp_packet_rr);
- if (!access_ok(VERIFY_READ, buff, packet_len)) - return -EFAULT; + skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); + if (!skb) + return -ENOMEM;
- if (__copy_from_user(&icmp_packet, buff, packet_len)) - return -EFAULT; + skb_reserve(skb, sizeof(struct ethhdr)); + icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
- if (icmp_packet.packet_type != BAT_ICMP) { + if (!access_ok(VERIFY_READ, buff, packet_len)) { + len = -EFAULT; + goto free_skb; + } + + if (__copy_from_user(icmp_packet, buff, packet_len)) { + len = -EFAULT; + goto free_skb; + } + + if (icmp_packet->packet_type != BAT_ICMP) { bat_dbg(DBG_BATMAN, bat_priv, "Error - can't send packet from char device: " "got bogus packet type (expected: BAT_ICMP)\n"); - return -EINVAL; + len = -EINVAL; + goto free_skb; }
- if (icmp_packet.msg_type != ECHO_REQUEST) { + if (icmp_packet->msg_type != ECHO_REQUEST) { bat_dbg(DBG_BATMAN, bat_priv, "Error - can't send packet from char device: " "got bogus message type (expected: ECHO_REQUEST)\n"); - return -EINVAL; + len = -EINVAL; + goto free_skb; }
- icmp_packet.uid = socket_client->index; + icmp_packet->uid = socket_client->index;
- if (icmp_packet.version != COMPAT_VERSION) { - icmp_packet.msg_type = PARAMETER_PROBLEM; - icmp_packet.ttl = COMPAT_VERSION; - bat_socket_add_packet(socket_client, &icmp_packet, packet_len); - goto out; + if (icmp_packet->version != COMPAT_VERSION) { + icmp_packet->msg_type = PARAMETER_PROBLEM; + icmp_packet->ttl = COMPAT_VERSION; + bat_socket_add_packet(socket_client, icmp_packet, packet_len); + goto free_skb; }
if (atomic_read(&module_state) != MODULE_ACTIVE) goto dst_unreach;
spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + orig_node = (struct orig_node *)hash_find(orig_hash, icmp_packet->dst);
if (!orig_node) goto unlock; @@ -226,22 +240,24 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (batman_if->if_status != IF_ACTIVE) goto dst_unreach;
- memcpy(icmp_packet.orig, + memcpy(icmp_packet->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
if (packet_len == sizeof(struct icmp_packet_rr)) - memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN);
- send_raw_packet((unsigned char *)&icmp_packet, - packet_len, batman_if, dstaddr); + + send_skb_packet(skb, batman_if, dstaddr);
goto out;
unlock: spin_unlock_irqrestore(&orig_hash_lock, flags); dst_unreach: - icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_socket_add_packet(socket_client, &icmp_packet, packet_len); + icmp_packet->msg_type = DESTINATION_UNREACHABLE; + bat_socket_add_packet(socket_client, icmp_packet, packet_len); +free_skb: + kfree_skb(skb); out: return len; }
From: Marek Lindner lindner_marek@yahoo.de
Batman-adv globally registered the batman-adv packet type and installed a hook to batman_skb_recv(). Each interface receiving a packet with that type would end up in this function which then had to loop through all batman-adv internal interface structures to find the its meta data. The more interfaces a system had the longer the loops might take. Each and every packet goes through this function making it a performance critical loop.
This patch installs the hook for each activated interface. The called batman_skb_recv() can distinguish these calls, therefore avoiding the loop through the interface structures.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/hard-interface.c | 12 ++++++++---- drivers/staging/batman-adv/main.c | 10 ---------- drivers/staging/batman-adv/types.h | 2 +- 3 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 82d3d55..f33c73f 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -265,6 +265,11 @@ int hardif_enable_interface(struct batman_if *batman_if) batman_if->if_status = IF_INACTIVE; orig_hash_add_if(batman_if, bat_priv->num_ifaces);
+ batman_if->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN); + batman_if->batman_adv_ptype.func = batman_skb_recv; + batman_if->batman_adv_ptype.dev = batman_if->net_dev; + dev_add_pack(&batman_if->batman_adv_ptype); + atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->frag_seqno, 1); bat_info(soft_device, "Adding interface: %s\n", batman_if->dev); @@ -319,6 +324,8 @@ void hardif_disable_interface(struct batman_if *batman_if) return;
bat_info(soft_device, "Removing interface: %s\n", batman_if->dev); + dev_remove_pack(&batman_if->batman_adv_ptype); + bat_priv->num_ifaces--; orig_hash_del_if(batman_if, bat_priv->num_ifaces);
@@ -468,6 +475,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct batman_if *batman_if; int ret;
+ batman_if = container_of(ptype, struct batman_if, batman_adv_ptype); skb = skb_share_check(skb, GFP_ATOMIC);
/* skb was released by skb_share_check() */ @@ -486,10 +494,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, || !skb_mac_header(skb))) goto err_free;
- 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_status != IF_ACTIVE) goto err_free; diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index c0a3373..eb0bfbe 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -49,11 +49,6 @@ struct net_device *soft_device; unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; atomic_t module_state;
-static struct packet_type batman_adv_packet_type __read_mostly = { - .type = __constant_htons(ETH_P_BATMAN), - .func = batman_skb_recv, -}; - struct workqueue_struct *bat_event_workqueue;
static int __init batman_init(void) @@ -103,7 +98,6 @@ static int __init batman_init(void) goto unreg_sysfs;
register_netdevice_notifier(&hard_if_notifier); - dev_add_pack(&batman_adv_packet_type);
pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) " "loaded\n", SOURCE_VERSION, REVISION_VERSION_STR, @@ -140,8 +134,6 @@ static void __exit batman_exit(void) soft_device = NULL; }
- dev_remove_pack(&batman_adv_packet_type); - destroy_workqueue(bat_event_workqueue); bat_event_workqueue = NULL; } @@ -185,8 +177,6 @@ void deactivate_module(void)
vis_quit();
- /* TODO: unregister BATMAN pack */ - originator_free();
hna_local_free(); diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index ac16575..2b06944 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -46,7 +46,7 @@ struct batman_if { int packet_len; struct kobject *hardif_obj; struct rcu_head rcu; - + struct packet_type batman_adv_ptype; };
/**
my_skb_push provided an easy way to allocate enough headroom in situation were we don't have enough space left and move the data pointer to the new position, but we didn't checked wether we are allowed to write to the new pushed header. This is for example a problem when the skb was cloned and thus doesn't have a private data part.
my_skb_head_push now replaces my_skb_push by using skb_cow_head to provide only a large enough, writable header without testing for the rest of the (maybe shared) data. It will also move the data pointer using skb_push when skb_cow_head doesn't fail.
This should give us enough flexibility in situation were skbs will be queued by underlying layers and still doesn't unnecessarily copy the data in situations when the skb was consumed right away during dev_queue_xmit.
Reported-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/send.c | 2 +- drivers/staging/batman-adv/soft-interface.c | 26 ++++++++++++++------------ drivers/staging/batman-adv/soft-interface.h | 2 +- drivers/staging/batman-adv/unicast.c | 6 +++--- 4 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index e874cae..b39c67b 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -73,7 +73,7 @@ int send_skb_packet(struct sk_buff *skb, }
/* push to the ethernet header. */ - if (my_skb_push(skb, sizeof(struct ethhdr)) < 0) + if (my_skb_head_push(skb, sizeof(struct ethhdr)) < 0) goto send_skb_err;
skb_reset_mac_header(skb); diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index d60b1a8..e8be209 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -31,8 +31,6 @@
static uint32_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid * broadcast storms */ -static int32_t skb_packets; -static int32_t skb_bad_packets;
unsigned char main_if_addr[ETH_ALEN]; static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); @@ -59,18 +57,22 @@ void set_main_if_addr(uint8_t *addr) memcpy(main_if_addr, addr, ETH_ALEN); }
-int my_skb_push(struct sk_buff *skb, unsigned int len) +int my_skb_head_push(struct sk_buff *skb, unsigned int len) { - int result = 0; + int result;
- skb_packets++; - if (skb_headroom(skb) < len) { - skb_bad_packets++; - result = pskb_expand_head(skb, len, 0, GFP_ATOMIC); + /** + * TODO: We must check if we can release all references to non-payload + * data using skb_header_release in our skbs to allow skb_cow_header to + * work optimally. This means that those skbs are not allowed to read + * or write any data which is before the current position of skb->data + * after that call and thus allow other skbs with the same data buffer + * to write freely in that area. + */ + result = skb_cow_head(skb, len);
- if (result < 0) - return result; - } + if (result < 0) + return result;
skb_push(skb, len); return 0; @@ -140,7 +142,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) /* ethernet packet should be broadcasted */ if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) {
- if (my_skb_push(skb, sizeof(struct bcast_packet)) < 0) + if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) goto dropped;
bcast_packet = (struct bcast_packet *)skb->data; diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h index 6364854..9dbf5fc 100644 --- a/drivers/staging/batman-adv/soft-interface.h +++ b/drivers/staging/batman-adv/soft-interface.h @@ -26,7 +26,7 @@ void set_main_if_addr(uint8_t *addr); void interface_setup(struct net_device *dev); int interface_tx(struct sk_buff *skb, struct net_device *dev); void interface_rx(struct sk_buff *skb, int hdr_size); -int my_skb_push(struct sk_buff *skb, unsigned int len); +int my_skb_head_push(struct sk_buff *skb, unsigned int len);
extern unsigned char main_if_addr[];
diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c index 153914e..61ebd38 100644 --- a/drivers/staging/batman-adv/unicast.c +++ b/drivers/staging/batman-adv/unicast.c @@ -163,8 +163,8 @@ static int unicast_send_frag_skb(struct sk_buff *skb, struct bat_priv *bat_priv, frag_skb = dev_alloc_skb(data_len - (data_len / 2) + hdr_len); skb_split(skb, frag_skb, data_len / 2);
- if (my_skb_push(frag_skb, hdr_len) < 0 || - my_skb_push(skb, hdr_len) < 0) + if (my_skb_head_push(frag_skb, hdr_len) < 0 || + my_skb_head_push(skb, hdr_len) < 0) goto drop_frag;
ucast_frag1 = (struct unicast_frag_packet *)skb->data; @@ -240,7 +240,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) return unicast_send_frag_skb(skb, bat_priv, batman_if, dstaddr, orig_node);
- if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) + if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0) goto dropped;
unicast_packet = (struct unicast_packet *)skb->data;
batman-adv tries to resend broadcasts on all interfaces up to three times. For each round and each interface it must provide a skb which gets consumed by the sending function.
It is unnecessary to copy the data of each broadcast because the actual data is either not shared or already copied by add_bcast_packet_to_list. So it is enough to just copy the skb control data
Reported-by: David S. Miller davem@davemloft.net Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/send.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index b39c67b..8dd9dd4 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -464,7 +464,7 @@ static void send_outstanding_bcast_packet(struct work_struct *work) rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { /* send a copy of the saved skb */ - skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC); + skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); if (skb1) send_skb_packet(skb1, batman_if, broadcast_addr);
All originator messages are send through aggregation buffers. Those buffers can directly be allocated as skb to reduce the cost of allocation an extra buffer and copying them to a new allocated skb directly before it gets send.
Now only the skb must be cloned in case of send_packet_to_if as it gets called by send_packet for each interface. Non-primary ogms must not cloned at all because they will only send once and the forward_packet structure is freed by send_outstanding_bat_packet afterwards.
Reported-by: David S. Miller davem@davemloft.net Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/aggregation.c | 22 ++++++++++++---------- drivers/staging/batman-adv/send.c | 24 ++++++++++++------------ drivers/staging/batman-adv/types.h | 1 - 3 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c index d738b7a..5896cf2 100644 --- a/drivers/staging/batman-adv/aggregation.c +++ b/drivers/staging/batman-adv/aggregation.c @@ -39,7 +39,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, struct forw_packet *forw_packet) { struct batman_packet *batman_packet = - (struct batman_packet *)forw_packet->packet_buff; + (struct batman_packet *)forw_packet->skb->data; int aggregated_bytes = forw_packet->packet_len + packet_len;
/** @@ -106,6 +106,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, { struct forw_packet *forw_packet_aggr; unsigned long flags; + unsigned char *skb_buff; /* FIXME: each batman_if will be attached to a softif */ struct bat_priv *bat_priv = netdev_priv(soft_device);
@@ -125,23 +126,22 @@ static void new_aggregated_packet(unsigned char *packet_buff, return; }
- forw_packet_aggr->packet_buff = kmalloc(MAX_AGGREGATION_BYTES, - GFP_ATOMIC); - if (!forw_packet_aggr->packet_buff) { + forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES + + sizeof(struct ethhdr)); + if (!forw_packet_aggr->skb) { if (!own_packet) atomic_inc(&bat_priv->batman_queue_left); kfree(forw_packet_aggr); return; } + skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
INIT_HLIST_NODE(&forw_packet_aggr->list);
+ skb_buff = skb_put(forw_packet_aggr->skb, packet_len); forw_packet_aggr->packet_len = packet_len; - memcpy(forw_packet_aggr->packet_buff, - packet_buff, - forw_packet_aggr->packet_len); + memcpy(skb_buff, packet_buff, packet_len);
- forw_packet_aggr->skb = NULL; forw_packet_aggr->own = own_packet; forw_packet_aggr->if_incoming = if_incoming; forw_packet_aggr->num_packets = 0; @@ -171,8 +171,10 @@ static void aggregate(struct forw_packet *forw_packet_aggr, int packet_len, bool direct_link) { - memcpy((forw_packet_aggr->packet_buff + forw_packet_aggr->packet_len), - packet_buff, packet_len); + unsigned char *skb_buff; + + skb_buff = skb_put(forw_packet_aggr->skb, packet_len); + memcpy(skb_buff, packet_buff, packet_len); forw_packet_aggr->packet_len += packet_len; forw_packet_aggr->num_packets++;
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 8dd9dd4..6b138b9 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -126,14 +126,14 @@ static void send_packet_to_if(struct forw_packet *forw_packet, uint8_t packet_num; int16_t buff_pos; struct batman_packet *batman_packet; + struct sk_buff *skb;
if (batman_if->if_status != IF_ACTIVE) return;
packet_num = 0; buff_pos = 0; - batman_packet = (struct batman_packet *) - (forw_packet->packet_buff); + batman_packet = (struct batman_packet *)forw_packet->skb->data;
/* adjust all flags and log packets */ while (aggregated_packet(buff_pos, @@ -165,12 +165,13 @@ static void send_packet_to_if(struct forw_packet *forw_packet, (batman_packet->num_hna * ETH_ALEN); packet_num++; batman_packet = (struct batman_packet *) - (forw_packet->packet_buff + buff_pos); + (forw_packet->skb->data + buff_pos); }
- send_raw_packet(forw_packet->packet_buff, - forw_packet->packet_len, - batman_if, broadcast_addr); + /* create clone because function is called more than once */ + skb = skb_clone(forw_packet->skb, GFP_ATOMIC); + if (skb) + send_skb_packet(skb, batman_if, broadcast_addr); }
/* send a batman packet */ @@ -180,7 +181,7 @@ static void send_packet(struct forw_packet *forw_packet) struct bat_priv *bat_priv = netdev_priv(soft_device); struct batman_if *batman_if; struct batman_packet *batman_packet = - (struct batman_packet *)(forw_packet->packet_buff); + (struct batman_packet *)(forw_packet->skb->data); unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) { @@ -206,10 +207,11 @@ static void send_packet(struct forw_packet *forw_packet) batman_packet->ttl, forw_packet->if_incoming->dev, forw_packet->if_incoming->addr_str);
- send_raw_packet(forw_packet->packet_buff, - forw_packet->packet_len, - forw_packet->if_incoming, + /* skb is only used once and than forw_packet is free'd */ + send_skb_packet(forw_packet->skb, forw_packet->if_incoming, broadcast_addr); + forw_packet->skb = NULL; + return; }
@@ -366,7 +368,6 @@ static void forw_packet_free(struct forw_packet *forw_packet) { if (forw_packet->skb) kfree_skb(forw_packet->skb); - kfree(forw_packet->packet_buff); kfree(forw_packet); }
@@ -425,7 +426,6 @@ int add_bcast_packet_to_list(struct sk_buff *skb) skb_reset_mac_header(skb);
forw_packet->skb = skb; - forw_packet->packet_buff = NULL;
/* how often did we send the bcast packet ? */ forw_packet->num_packets = 0; diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 2b06944..4b2e832 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -161,7 +161,6 @@ struct forw_packet { unsigned long send_time; uint8_t own; struct sk_buff *skb; - unsigned char *packet_buff; uint16_t packet_len; uint32_t direct_link_flags; uint8_t num_packets;
The vis information structure is used in a way that it can be transfered directly as packet. It still had to be copied into a skb because of an extra buffer used for the actual preparation of the data. This is unnecessary and can be replaced by a simple clone instead of an full copy before each send.
This makes also the send_raw_packet function obsolete.
Reported-by: David S. Miller davem@davemloft.net Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/TODO | 2 - drivers/staging/batman-adv/send.c | 17 --- drivers/staging/batman-adv/send.h | 2 - drivers/staging/batman-adv/vis.c | 206 ++++++++++++++++++++++++------------- drivers/staging/batman-adv/vis.h | 2 +- 5 files changed, 133 insertions(+), 96 deletions(-)
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index d8bf845..1457c7f 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -1,5 +1,3 @@ - * Save/cache packets direktly as skb instead of using a normal memory region - and copying it in a skb using send_raw_packet and similar functions * Request a new review * Process the comments from the review * Move into mainline proper diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 6b138b9..aebd6c3 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -99,23 +99,6 @@ send_skb_err: return NET_XMIT_DROP; }
-/* sends a raw packet. */ -void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, - struct batman_if *batman_if, uint8_t *dst_addr) -{ - struct sk_buff *skb; - char *data; - - skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr)); - if (!skb) - return; - data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr)); - memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len); - /* pull back to the batman "network header" */ - skb_pull(skb, sizeof(struct ethhdr)); - send_skb_packet(skb, batman_if, dst_addr); -} - /* Send a packet to a given interface */ static void send_packet_to_if(struct forw_packet *forw_packet, struct batman_if *batman_if) diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h index b64c627..0cfe027 100644 --- a/drivers/staging/batman-adv/send.h +++ b/drivers/staging/batman-adv/send.h @@ -27,8 +27,6 @@ int send_skb_packet(struct sk_buff *skb, struct batman_if *batman_if, uint8_t *dst_addr); -void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, - struct batman_if *batman_if, uint8_t *dst_addr); void schedule_own_packet(struct batman_if *batman_if); void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 4b6a504..e89a710 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -43,6 +43,8 @@ _dummy > smallest_signed_int(_dummy); }) #define seq_after(x, y) seq_before(y, x)
+#define MAX_VIS_PACKET_SIZE 1000 + static struct hashtable_t *vis_hash; static DEFINE_SPINLOCK(vis_hash_lock); static DEFINE_SPINLOCK(recv_list_lock); @@ -65,6 +67,7 @@ static void free_info(struct kref *ref) kfree(entry); } spin_unlock_irqrestore(&recv_list_lock, flags); + kfree_skb(info->skb_packet); kfree(info); }
@@ -72,9 +75,12 @@ static void free_info(struct kref *ref) static int vis_info_cmp(void *data1, void *data2) { struct vis_info *d1, *d2; + struct vis_packet *p1, *p2; d1 = data1; d2 = data2; - return compare_orig(d1->packet.vis_orig, d2->packet.vis_orig); + p1 = (struct vis_packet *)d1->skb_packet->data; + p2 = (struct vis_packet *)d2->skb_packet->data; + return compare_orig(p1->vis_orig, p2->vis_orig); }
/* hash function to choose an entry in a hash table of given size */ @@ -82,11 +88,13 @@ static int vis_info_cmp(void *data1, void *data2) static int vis_info_choose(void *data, int size) { struct vis_info *vis_info = data; + struct vis_packet *packet; unsigned char *key; uint32_t hash = 0; size_t i;
- key = vis_info->packet.vis_orig; + packet = (struct vis_packet *)vis_info->skb_packet->data; + key = packet->vis_orig; for (i = 0; i < ETH_ALEN; i++) { hash += key[i]; hash += (hash << 10); @@ -179,6 +187,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) HASHIT(hashit); HASHIT(hashit_count); struct vis_info *info; + struct vis_packet *packet; struct vis_info_entry *entries; struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); @@ -201,22 +210,22 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) spin_lock_irqsave(&vis_hash_lock, flags); while (hash_iterate(vis_hash, &hashit_count)) { info = hashit_count.bucket->data; + packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) - ((char *)info + sizeof(struct vis_info)); + ((char *)packet + sizeof(struct vis_packet));
- for (i = 0; i < info->packet.entries; i++) { + for (i = 0; i < packet->entries; i++) { if (entries[i].quality == 0) continue; vis_data_insert_interface(entries[i].src, &vis_if_list, - compare_orig(entries[i].src, - info->packet.vis_orig)); + compare_orig(entries[i].src, packet->vis_orig)); }
hlist_for_each_entry(entry, pos, &vis_if_list, list) { - buf_size += 18 + 26 * info->packet.entries; + buf_size += 18 + 26 * packet->entries;
/* add primary/secondary records */ - if (compare_orig(entry->addr, info->packet.vis_orig)) + if (compare_orig(entry->addr, packet->vis_orig)) buf_size += vis_data_count_prim_sec(&vis_if_list);
@@ -239,15 +248,15 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; + packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) - ((char *)info + sizeof(struct vis_info)); + ((char *)packet + sizeof(struct vis_packet));
- for (i = 0; i < info->packet.entries; i++) { + for (i = 0; i < packet->entries; i++) { if (entries[i].quality == 0) continue; vis_data_insert_interface(entries[i].src, &vis_if_list, - compare_orig(entries[i].src, - info->packet.vis_orig)); + compare_orig(entries[i].src, packet->vis_orig)); }
hlist_for_each_entry(entry, pos, &vis_if_list, list) { @@ -255,14 +264,14 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) buff_pos += sprintf(buff + buff_pos, "%s,", tmp_addr_str);
- for (i = 0; i < info->packet.entries; i++) + for (i = 0; i < packet->entries; i++) buff_pos += vis_data_read_entry(buff + buff_pos, &entries[i], entry->addr, entry->primary);
/* add primary/secondary records */ - if (compare_orig(entry->addr, info->packet.vis_orig)) + if (compare_orig(entry->addr, packet->vis_orig)) buff_pos += vis_data_read_prim_sec(buff + buff_pos, &vis_if_list); @@ -345,7 +354,9 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, int make_broadcast) { struct vis_info *info, *old_info; + struct vis_packet *search_packet, *old_packet; struct vis_info search_elem; + struct vis_packet *packet;
*is_new = 0; /* sanity check */ @@ -353,13 +364,21 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, return NULL;
/* see if the packet is already in vis_hash */ - memcpy(search_elem.packet.vis_orig, vis_packet->vis_orig, ETH_ALEN); + search_elem.skb_packet = dev_alloc_skb(sizeof(struct vis_packet)); + if (!search_elem.skb_packet) + return NULL; + search_packet = (struct vis_packet *)skb_put(search_elem.skb_packet, + sizeof(struct vis_packet)); + + memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); old_info = hash_find(vis_hash, &search_elem); + kfree_skb(search_elem.skb_packet);
if (old_info != NULL) { + old_packet = (struct vis_packet *)old_info->skb_packet->data; if (!seq_after(ntohl(vis_packet->seqno), - ntohl(old_info->packet.seqno))) { - if (old_info->packet.seqno == vis_packet->seqno) { + ntohl(old_packet->seqno))) { + if (old_packet->seqno == vis_packet->seqno) { recv_list_add(&old_info->recv_list, vis_packet->sender_orig); return old_info; @@ -374,30 +393,39 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, kref_put(&old_info->refcount, free_info); }
- info = kmalloc(sizeof(struct vis_info) + vis_info_len, GFP_ATOMIC); + info = kmalloc(sizeof(struct vis_info), GFP_ATOMIC); if (info == NULL) return NULL;
+ info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) + + vis_info_len + sizeof(struct ethhdr)); + if (!info->skb_packet) { + kfree(info); + return NULL; + } + skb_reserve(info->skb_packet, sizeof(struct ethhdr)); + packet = (struct vis_packet *)skb_put(info->skb_packet, + sizeof(struct vis_packet) + + vis_info_len); + kref_init(&info->refcount); INIT_LIST_HEAD(&info->send_list); INIT_LIST_HEAD(&info->recv_list); info->first_seen = jiffies; - memcpy(&info->packet, vis_packet, - sizeof(struct vis_packet) + vis_info_len); + memcpy(packet, vis_packet, sizeof(struct vis_packet) + vis_info_len);
/* initialize and add new packet. */ *is_new = 1;
/* Make it a broadcast packet, if required */ if (make_broadcast) - memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN); + memcpy(packet->target_orig, broadcast_addr, ETH_ALEN);
/* repair if entries is longer than packet. */ - if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len) - info->packet.entries = vis_info_len / - sizeof(struct vis_info_entry); + if (packet->entries * sizeof(struct vis_info_entry) > vis_info_len) + packet->entries = vis_info_len / sizeof(struct vis_info_entry);
- recv_list_add(&info->recv_list, info->packet.sender_orig); + recv_list_add(&info->recv_list, packet->sender_orig);
/* try to add it */ if (hash_add(vis_hash, info) < 0) { @@ -440,6 +468,7 @@ void receive_client_update_packet(struct bat_priv *bat_priv, int vis_info_len) { struct vis_info *info; + struct vis_packet *packet; int is_new; unsigned long flags; int vis_server = atomic_read(&bat_priv->vis_mode); @@ -456,20 +485,23 @@ void receive_client_update_packet(struct bat_priv *bat_priv,
spin_lock_irqsave(&vis_hash_lock, flags); info = add_packet(vis_packet, vis_info_len, &is_new, are_target); + if (info == NULL) goto end; /* note that outdated packets will be dropped at this point. */
+ packet = (struct vis_packet *)info->skb_packet->data;
/* send only if we're the target server or ... */ if (are_target && is_new) { - info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ + packet->vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ send_list_add(info);
/* ... we're not the recipient (and thus need to forward). */ - } else if (!is_my_mac(info->packet.target_orig)) { + } else if (!is_my_mac(packet->target_orig)) { send_list_add(info); } + end: spin_unlock_irqrestore(&vis_hash_lock, flags); } @@ -482,8 +514,11 @@ static int find_best_vis_server(struct vis_info *info) { HASHIT(hashit); struct orig_node *orig_node; + struct vis_packet *packet; int best_tq = -1;
+ packet = (struct vis_packet *)info->skb_packet->data; + while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; if ((orig_node != NULL) && @@ -491,8 +526,7 @@ static int find_best_vis_server(struct vis_info *info) (orig_node->flags & VIS_SERVER) && (orig_node->router->tq_avg > best_tq)) { best_tq = orig_node->router->tq_avg; - memcpy(info->packet.target_orig, orig_node->orig, - ETH_ALEN); + memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); } } return best_tq; @@ -501,8 +535,11 @@ static int find_best_vis_server(struct vis_info *info) /* Return true if the vis packet is full. */ static bool vis_packet_full(struct vis_info *info) { - if (info->packet.entries + 1 > - (1000 - sizeof(struct vis_info)) / sizeof(struct vis_info_entry)) + struct vis_packet *packet; + packet = (struct vis_packet *)info->skb_packet->data; + + if (MAX_VIS_PACKET_SIZE / sizeof(struct vis_info_entry) + < packet->entries + 1) return true; return false; } @@ -515,21 +552,23 @@ static int generate_vis_packet(struct bat_priv *bat_priv) HASHIT(hashit_global); struct orig_node *orig_node; struct vis_info *info = (struct vis_info *)my_vis_info; - struct vis_info_entry *entry, *entry_array; + struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; + struct vis_info_entry *entry; struct hna_local_entry *hna_local_entry; int best_tq = -1; unsigned long flags;
info->first_seen = jiffies; - info->packet.vis_type = atomic_read(&bat_priv->vis_mode); + packet->vis_type = atomic_read(&bat_priv->vis_mode);
spin_lock_irqsave(&orig_hash_lock, flags); - memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN); - info->packet.ttl = TTL; - info->packet.seqno = htonl(ntohl(info->packet.seqno) + 1); - info->packet.entries = 0; + memcpy(packet->target_orig, broadcast_addr, ETH_ALEN); + packet->ttl = TTL; + packet->seqno = htonl(ntohl(packet->seqno) + 1); + packet->entries = 0; + skb_trim(info->skb_packet, sizeof(struct vis_packet));
- if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) { + if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) { best_tq = find_best_vis_server(info); if (best_tq < 0) { spin_unlock_irqrestore(&orig_hash_lock, flags); @@ -537,9 +576,6 @@ static int generate_vis_packet(struct bat_priv *bat_priv) } }
- entry_array = (struct vis_info_entry *) - ((char *)info + sizeof(struct vis_info)); - while (hash_iterate(orig_hash, &hashit_global)) { orig_node = hashit_global.bucket->data; if (orig_node->router != NULL @@ -550,13 +586,14 @@ static int generate_vis_packet(struct bat_priv *bat_priv) && orig_node->router->tq_avg > 0) {
/* fill one entry into buffer. */ - entry = &entry_array[info->packet.entries]; + entry = (struct vis_info_entry *) + skb_put(info->skb_packet, sizeof(*entry)); memcpy(entry->src, orig_node->router->if_incoming->net_dev->dev_addr, ETH_ALEN); memcpy(entry->dest, orig_node->orig, ETH_ALEN); entry->quality = orig_node->router->tq_avg; - info->packet.entries++; + packet->entries++;
if (vis_packet_full(info)) { spin_unlock_irqrestore(&orig_hash_lock, flags); @@ -570,11 +607,12 @@ static int generate_vis_packet(struct bat_priv *bat_priv) spin_lock_irqsave(&hna_local_hash_lock, flags); while (hash_iterate(hna_local_hash, &hashit_local)) { hna_local_entry = hashit_local.bucket->data; - entry = &entry_array[info->packet.entries]; + entry = (struct vis_info_entry *)skb_put(info->skb_packet, + sizeof(*entry)); memset(entry->src, 0, ETH_ALEN); memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); entry->quality = 0; /* 0 means HNA */ - info->packet.entries++; + packet->entries++;
if (vis_packet_full(info)) { spin_unlock_irqrestore(&hna_local_hash_lock, flags); @@ -605,15 +643,18 @@ static void purge_vis_packets(void) } }
-static void broadcast_vis_packet(struct vis_info *info, int packet_length) +static void broadcast_vis_packet(struct vis_info *info) { HASHIT(hashit); struct orig_node *orig_node; + struct vis_packet *packet; + struct sk_buff *skb; unsigned long flags; struct batman_if *batman_if; uint8_t dstaddr[ETH_ALEN];
spin_lock_irqsave(&orig_hash_lock, flags); + packet = (struct vis_packet *)info->skb_packet->data;
/* send to all routers in range. */ while (hash_iterate(orig_hash, &hashit)) { @@ -629,31 +670,35 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length) if (recv_list_is_in(&info->recv_list, orig_node->orig)) continue;
- memcpy(info->packet.target_orig, orig_node->orig, ETH_ALEN); + memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); spin_unlock_irqrestore(&orig_hash_lock, flags);
- send_raw_packet((unsigned char *)&info->packet, - packet_length, batman_if, dstaddr); + skb = skb_clone(info->skb_packet, GFP_ATOMIC); + if (skb) + send_skb_packet(skb, batman_if, dstaddr);
spin_lock_irqsave(&orig_hash_lock, flags);
} spin_unlock_irqrestore(&orig_hash_lock, flags); - memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN); + memcpy(packet->target_orig, broadcast_addr, ETH_ALEN); }
-static void unicast_vis_packet(struct vis_info *info, int packet_length) +static void unicast_vis_packet(struct vis_info *info) { struct orig_node *orig_node; + struct sk_buff *skb; + struct vis_packet *packet; unsigned long flags; struct batman_if *batman_if; uint8_t dstaddr[ETH_ALEN];
spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *) - hash_find(orig_hash, info->packet.target_orig)); + packet = (struct vis_packet *)info->skb_packet->data; + orig_node = ((struct orig_node *)hash_find(orig_hash, + packet->target_orig));
if ((!orig_node) || (!orig_node->router)) goto out; @@ -664,8 +709,10 @@ static void unicast_vis_packet(struct vis_info *info, int packet_length) memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); spin_unlock_irqrestore(&orig_hash_lock, flags);
- send_raw_packet((unsigned char *)&info->packet, - packet_length, batman_if, dstaddr); + skb = skb_clone(info->skb_packet, GFP_ATOMIC); + if (skb) + send_skb_packet(skb, batman_if, dstaddr); + return;
out: @@ -675,24 +722,22 @@ out: /* only send one vis packet. called from send_vis_packets() */ static void send_vis_packet(struct vis_info *info) { - int packet_length; + struct vis_packet *packet;
- if (info->packet.ttl < 2) { + packet = (struct vis_packet *)info->skb_packet->data; + if (packet->ttl < 2) { pr_warning("Error - can't send vis packet: ttl exceeded\n"); return; }
- memcpy(info->packet.sender_orig, main_if_addr, ETH_ALEN); - info->packet.ttl--; + memcpy(packet->sender_orig, main_if_addr, ETH_ALEN); + packet->ttl--;
- packet_length = sizeof(struct vis_packet) + - info->packet.entries * sizeof(struct vis_info_entry); - - if (is_bcast(info->packet.target_orig)) - broadcast_vis_packet(info, packet_length); + if (is_bcast(packet->target_orig)) + broadcast_vis_packet(info); else - unicast_vis_packet(info, packet_length); - info->packet.ttl++; /* restore TTL */ + unicast_vis_packet(info); + packet->ttl++; /* restore TTL */ }
/* called from timer; send (and maybe generate) vis packet. */ @@ -732,6 +777,7 @@ static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets); * initialized (e.g. bat0 is initialized, interfaces have been added) */ int vis_init(void) { + struct vis_packet *packet; unsigned long flags; if (vis_hash) return 1; @@ -744,27 +790,36 @@ int vis_init(void) goto err; }
- my_vis_info = kmalloc(1000, GFP_ATOMIC); + my_vis_info = kmalloc(MAX_VIS_PACKET_SIZE, GFP_ATOMIC); if (!my_vis_info) { pr_err("Can't initialize vis packet\n"); goto err; }
+ my_vis_info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) + + MAX_VIS_PACKET_SIZE + + sizeof(struct ethhdr)); + if (!my_vis_info->skb_packet) + goto free_info; + skb_reserve(my_vis_info->skb_packet, sizeof(struct ethhdr)); + packet = (struct vis_packet *)skb_put(my_vis_info->skb_packet, + sizeof(struct vis_packet)); + /* prefill the vis info */ my_vis_info->first_seen = jiffies - msecs_to_jiffies(VIS_INTERVAL); INIT_LIST_HEAD(&my_vis_info->recv_list); INIT_LIST_HEAD(&my_vis_info->send_list); kref_init(&my_vis_info->refcount); - my_vis_info->packet.version = COMPAT_VERSION; - my_vis_info->packet.packet_type = BAT_VIS; - my_vis_info->packet.ttl = TTL; - my_vis_info->packet.seqno = 0; - my_vis_info->packet.entries = 0; + packet->version = COMPAT_VERSION; + packet->packet_type = BAT_VIS; + packet->ttl = TTL; + packet->seqno = 0; + packet->entries = 0;
INIT_LIST_HEAD(&send_list);
- memcpy(my_vis_info->packet.vis_orig, main_if_addr, ETH_ALEN); - memcpy(my_vis_info->packet.sender_orig, main_if_addr, ETH_ALEN); + memcpy(packet->vis_orig, main_if_addr, ETH_ALEN); + memcpy(packet->sender_orig, main_if_addr, ETH_ALEN);
if (hash_add(vis_hash, my_vis_info) < 0) { pr_err("Can't add own vis packet into hash\n"); @@ -777,6 +832,9 @@ int vis_init(void) start_vis_timer(); return 1;
+free_info: + kfree(my_vis_info); + my_vis_info = NULL; err: spin_unlock_irqrestore(&vis_hash_lock, flags); vis_quit(); diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index bb13bf1..19dc325 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -32,7 +32,7 @@ struct vis_info { struct list_head send_list; struct kref refcount; /* this packet might be part of the vis send queue. */ - struct vis_packet packet; + struct sk_buff *skb_packet; /* vis_info may follow here*/ } __attribute__((packed));
We can use skb_cow instead of a handwritten function to test and create a writable skb buffer. This also allows us to pre-allocate headroom to be able to send the data without re-allocating the buffer again to add the ethernet header.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/routing.c | 77 ++++++++++----------------------- 1 files changed, 24 insertions(+), 53 deletions(-)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index d8e77ac..7e993a2 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -742,7 +742,6 @@ int recv_bat_packet(struct sk_buff *skb, { struct ethhdr *ethhdr; unsigned long flags; - struct sk_buff *skb_old;
/* drop packet if it has not necessary minimum size */ if (skb_headlen(skb) < sizeof(struct batman_packet)) @@ -758,18 +757,11 @@ int recv_bat_packet(struct sk_buff *skb, if (is_bcast(ethhdr->h_source)) return NET_RX_DROP;
- /* TODO: we use headlen instead of "length", because - * only this data is paged in. */ - /* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, skb_headlen(skb))) { - skb_old = skb; - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) - return NET_RX_DROP; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - kfree_skb(skb_old); - } + if (skb_cow(skb, 0) < 0) + return NET_RX_DROP; + + ethhdr = (struct ethhdr *)skb_mac_header(skb);
spin_lock_irqsave(&orig_hash_lock, flags); receive_aggr_bat_packet(ethhdr, @@ -789,7 +781,6 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) struct orig_node *orig_node; struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; - struct sk_buff *skb_old; struct batman_if *batman_if; int ret; unsigned long flags; @@ -824,16 +815,11 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ - skb_old = NULL; - if (!skb_clone_writable(skb, icmp_len)) { - skb_old = skb; - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) - return NET_RX_DROP; - icmp_packet = (struct icmp_packet_rr *)skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - kfree_skb(skb_old); - } + if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + return NET_RX_DROP; + + icmp_packet = (struct icmp_packet_rr *)skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); memcpy(icmp_packet->orig, @@ -857,7 +843,6 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) struct orig_node *orig_node; struct icmp_packet *icmp_packet; struct ethhdr *ethhdr; - struct sk_buff *skb_old; struct batman_if *batman_if; int ret; unsigned long flags; @@ -893,15 +878,11 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, icmp_len)) { - skb_old = skb; - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) - return NET_RX_DROP; - icmp_packet = (struct icmp_packet *) skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - kfree_skb(skb_old); - } + if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + return NET_RX_DROP; + + icmp_packet = (struct icmp_packet *) skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); memcpy(icmp_packet->orig, @@ -924,7 +905,6 @@ int recv_icmp_packet(struct sk_buff *skb) struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; struct orig_node *orig_node; - struct sk_buff *skb_old; struct batman_if *batman_if; int hdr_size = sizeof(struct icmp_packet); int ret; @@ -990,15 +970,11 @@ int recv_icmp_packet(struct sk_buff *skb) spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, hdr_size)) { - skb_old = skb; - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) - return NET_RX_DROP; - icmp_packet = (struct icmp_packet_rr *)skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - kfree_skb(skb_old); - } + if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + return NET_RX_DROP; + + icmp_packet = (struct icmp_packet_rr *)skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* decrement ttl */ icmp_packet->ttl--; @@ -1137,7 +1113,6 @@ static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, struct orig_node *orig_node; struct neigh_node *router; struct batman_if *batman_if; - struct sk_buff *skb_old; uint8_t dstaddr[ETH_ALEN]; unsigned long flags; struct unicast_packet *unicast_packet = @@ -1173,15 +1148,11 @@ static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ - if (!skb_clone_writable(skb, hdr_size)) { - skb_old = skb; - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) - return NET_RX_DROP; - unicast_packet = (struct unicast_packet *) skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - kfree_skb(skb_old); - } + if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + return NET_RX_DROP; + + unicast_packet = (struct unicast_packet *) skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* decrement ttl */ unicast_packet->ttl--;
We must ensure that all interesting data is linear and not paged out to access all information in a header or a full batman-adv related packet. Otherwise we may drop packets which have non-linear headers but which hold valid data.
This doesn't affect non-linear skbs which have all headers in a linear head unless we must process the whole packet like in ogms or vis packets.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/hard-interface.c | 2 +- drivers/staging/batman-adv/routing.c | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index f33c73f..c1863d2 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -486,7 +486,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, goto err_free;
/* packet should hold at least type and version */ - if (unlikely(skb_headlen(skb) < 2)) + if (unlikely(!pskb_may_pull(skb, 2))) goto err_free;
/* expect a valid ethernet header here. */ diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 7e993a2..6009adc 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -744,7 +744,7 @@ int recv_bat_packet(struct sk_buff *skb, unsigned long flags;
/* drop packet if it has not necessary minimum size */ - if (skb_headlen(skb) < sizeof(struct batman_packet)) + if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet)))) return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb); @@ -761,6 +761,10 @@ int recv_bat_packet(struct sk_buff *skb, if (skb_cow(skb, 0) < 0) return NET_RX_DROP;
+ /* keep skb linear */ + if (skb_linearize(skb) < 0) + return NET_RX_DROP; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
spin_lock_irqsave(&orig_hash_lock, flags); @@ -914,11 +918,11 @@ int recv_icmp_packet(struct sk_buff *skb) /** * we truncate all incoming icmp packets if they don't match our size */ - if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr)) + if (skb->len >= sizeof(struct icmp_packet_rr)) hdr_size = sizeof(struct icmp_packet_rr);
/* drop packet if it has not necessary minimum size */ - if (skb_headlen(skb) < hdr_size) + if (unlikely(!pskb_may_pull(skb, hdr_size))) return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb); @@ -1087,7 +1091,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */ - if (skb_headlen(skb) < hdr_size) + if (unlikely(!pskb_may_pull(skb, hdr_size))) return -1;
ethhdr = (struct ethhdr *) skb_mac_header(skb); @@ -1247,7 +1251,7 @@ int recv_bcast_packet(struct sk_buff *skb) unsigned long flags;
/* drop packet if it has not necessary minimum size */ - if (skb_headlen(skb) < hdr_size) + if (unlikely(!pskb_may_pull(skb, hdr_size))) return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb); @@ -1320,7 +1324,11 @@ int recv_vis_packet(struct sk_buff *skb) struct bat_priv *bat_priv; int hdr_size = sizeof(struct vis_packet);
- if (skb_headlen(skb) < hdr_size) + /* keep skb linear */ + if (skb_linearize(skb) < 0) + return NET_RX_DROP; + + if (unlikely(!pskb_may_pull(skb, hdr_size))) return NET_RX_DROP;
vis_packet = (struct vis_packet *) skb->data; @@ -1342,13 +1350,11 @@ int recv_vis_packet(struct sk_buff *skb)
switch (vis_packet->vis_type) { case VIS_TYPE_SERVER_SYNC: - /* TODO: handle fragmented skbs properly */ receive_server_sync_packet(bat_priv, vis_packet, skb_headlen(skb)); break;
case VIS_TYPE_CLIENT_UPDATE: - /* TODO: handle fragmented skbs properly */ receive_client_update_packet(bat_priv, vis_packet, skb_headlen(skb)); break;
From: Marek Lindner lindner_marek@yahoo.de
This patch replaces the static bat0 interface with a dynamic/abstracted approach. It is now possible to create multiple batX interfaces by assigning hard interfaces to them. Each batX interface acts as an independent mesh network. A soft interface is removed once no hard interface references it any longer.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/aggregation.c | 13 +- drivers/staging/batman-adv/bat_sysfs.c | 67 ++++------ drivers/staging/batman-adv/bitarray.c | 7 +- drivers/staging/batman-adv/bitarray.h | 4 +- drivers/staging/batman-adv/hard-interface.c | 131 ++++++++++++------- drivers/staging/batman-adv/hard-interface.h | 6 +- drivers/staging/batman-adv/hash.c | 6 +- drivers/staging/batman-adv/hash.h | 4 +- drivers/staging/batman-adv/icmp_socket.c | 1 + drivers/staging/batman-adv/main.c | 54 +-------- drivers/staging/batman-adv/main.h | 2 - drivers/staging/batman-adv/originator.c | 39 +++--- drivers/staging/batman-adv/originator.h | 2 +- drivers/staging/batman-adv/routing.c | 163 +++++++++++++----------- drivers/staging/batman-adv/routing.h | 12 +- drivers/staging/batman-adv/send.c | 48 ++++---- drivers/staging/batman-adv/send.h | 2 +- drivers/staging/batman-adv/soft-interface.c | 118 ++++++++++++++--- drivers/staging/batman-adv/soft-interface.h | 8 +- drivers/staging/batman-adv/translation-table.c | 57 +++++---- drivers/staging/batman-adv/translation-table.h | 13 +- drivers/staging/batman-adv/types.h | 1 + drivers/staging/batman-adv/vis.c | 13 +- 23 files changed, 419 insertions(+), 352 deletions(-)
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c index 5896cf2..6e10fe5 100644 --- a/drivers/staging/batman-adv/aggregation.c +++ b/drivers/staging/batman-adv/aggregation.c @@ -97,18 +97,15 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* create a new aggregated packet and add this packet to it */ -static void new_aggregated_packet(unsigned char *packet_buff, - int packet_len, - unsigned long send_time, - bool direct_link, - struct batman_if *if_incoming, - int own_packet) +static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, + unsigned long send_time, bool direct_link, + struct batman_if *if_incoming, + int own_packet) { struct forw_packet *forw_packet_aggr; unsigned long flags; unsigned char *skb_buff; - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
/* own packet should always be scheduled */ if (!own_packet) { diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index b9fe391..052f9e8 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -180,9 +180,7 @@ static ssize_t store_frag(struct kobject *kobj, struct attribute *attr, frag_enabled_tmp == 1 ? "enabled" : "disabled");
atomic_set(&bat_priv->frag_enabled, (unsigned)frag_enabled_tmp); - - update_min_mtu(); - + update_min_mtu(net_dev); return count; }
@@ -358,20 +356,6 @@ int sysfs_add_meshif(struct net_device *dev) struct bat_attribute **bat_attr; int err;
- /* FIXME: should be done in the general mesh setup - routine as soon as we have it */ - atomic_set(&bat_priv->aggregation_enabled, 1); - atomic_set(&bat_priv->bonding_enabled, 0); - atomic_set(&bat_priv->frag_enabled, 1); - atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); - atomic_set(&bat_priv->orig_interval, 1000); - atomic_set(&bat_priv->log_level, 0); - atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN); - atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN); - - bat_priv->primary_if = NULL; - bat_priv->num_ifaces = 0; - bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR, batif_kobject); if (!bat_priv->mesh_obj) { @@ -441,32 +425,39 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, if (!batman_if) return count;
+ if (buff[count - 1] == '\n') + buff[count - 1] = '\0'; + + if (strlen(buff) >= IFNAMSIZ) { + pr_err("Invalid parameter for 'mesh_iface' setting received: " + "interface name too long '%s'\n", buff); + return -EINVAL; + } + 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'; - - pr_err("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 + status_tmp = IF_I_WANT_YOU; + + if ((batman_if->if_status == status_tmp) || ((batman_if->soft_iface) && + (strncmp(batman_if->soft_iface->name, buff, IFNAMSIZ) == 0))) + return count; + + if (status_tmp == IF_NOT_IN_USE) { + rtnl_lock(); + hardif_disable_interface(batman_if); + rtnl_unlock(); + return count; + } + + /* if the interface already is in use */ + if (batman_if->if_status != IF_NOT_IN_USE) { + rtnl_lock(); hardif_disable_interface(batman_if); + rtnl_unlock(); + }
- return (status_tmp < 0 ? status_tmp : count); + return hardif_enable_interface(batman_if, buff); }
static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr, diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c index 9dbaf1e..814274f 100644 --- a/drivers/staging/batman-adv/bitarray.c +++ b/drivers/staging/batman-adv/bitarray.c @@ -127,11 +127,10 @@ static void bit_reset_window(TYPE_OF_WORD *seq_bits) * 1 if the window was moved (either new or very old) * 0 if the window was not moved/shifted. */ -char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff, - int8_t set_mark) +char bit_get_packet(void *priv, TYPE_OF_WORD *seq_bits, + int32_t seq_num_diff, int8_t set_mark) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = (struct bat_priv *)priv;
/* sequence number is slightly older. We already got a sequence number * higher than this one, so we just mark it. */ diff --git a/drivers/staging/batman-adv/bitarray.h b/drivers/staging/batman-adv/bitarray.h index c0c1730..d961d56 100644 --- a/drivers/staging/batman-adv/bitarray.h +++ b/drivers/staging/batman-adv/bitarray.h @@ -38,8 +38,8 @@ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n);
/* receive and process one packet, returns 1 if received seq_num is considered * new, 0 if old */ -char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff, - int8_t set_mark); +char bit_get_packet(void *priv, TYPE_OF_WORD *seq_bits, + int32_t seq_num_diff, int8_t set_mark);
/* count the hamming weight, how many good packets did we receive? */ int bit_packet_count(TYPE_OF_WORD *seq_bits); diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index c1863d2..d31cfc3 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -128,9 +128,6 @@ static bool hardif_is_iface_up(struct batman_if *batman_if)
static void update_mac_addresses(struct batman_if *batman_if) { - if (!batman_if || !batman_if->packet_buff) - return; - addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, @@ -160,24 +157,28 @@ static void check_known_mac_addr(uint8_t *addr) rcu_read_unlock(); }
-int hardif_min_mtu(void) +int hardif_min_mtu(struct net_device *soft_iface) { + struct bat_priv *bat_priv = netdev_priv(soft_iface); 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; - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device);
if (atomic_read(&bat_priv->frag_enabled)) goto out;
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); + if ((batman_if->if_status != IF_ACTIVE) && + (batman_if->if_status != IF_TO_BE_ACTIVATED)) + continue; + + if (batman_if->soft_iface != soft_iface) + continue; + + min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN, + min_mtu); } rcu_read_unlock(); out: @@ -185,22 +186,24 @@ out: }
/* adjusts the MTU if a new interface with a smaller MTU appeared. */ -void update_min_mtu(void) +void update_min_mtu(struct net_device *soft_iface) { int min_mtu;
- min_mtu = hardif_min_mtu(); - if (soft_device->mtu != min_mtu) - soft_device->mtu = min_mtu; + min_mtu = hardif_min_mtu(soft_iface); + if (soft_iface->mtu != min_mtu) + soft_iface->mtu = min_mtu; }
-static void hardif_activate_interface(struct net_device *net_dev, - struct bat_priv *bat_priv, - struct batman_if *batman_if) +static void hardif_activate_interface(struct batman_if *batman_if) { + struct bat_priv *bat_priv; + if (batman_if->if_status != IF_INACTIVE) return;
+ bat_priv = netdev_priv(batman_if->soft_iface); + update_mac_addresses(batman_if); batman_if->if_status = IF_TO_BE_ACTIVATED;
@@ -211,17 +214,17 @@ static void hardif_activate_interface(struct net_device *net_dev, if (!bat_priv->primary_if) set_primary_if(bat_priv, batman_if);
- bat_info(net_dev, "Interface activated: %s\n", batman_if->dev); + bat_info(batman_if->soft_iface, "Interface activated: %s\n", + batman_if->dev);
if (atomic_read(&module_state) == MODULE_INACTIVE) activate_module();
- update_min_mtu(); + update_min_mtu(batman_if->soft_iface); return; }
-static void hardif_deactivate_interface(struct net_device *net_dev, - struct batman_if *batman_if) +static void hardif_deactivate_interface(struct batman_if *batman_if) { if ((batman_if->if_status != IF_ACTIVE) && (batman_if->if_status != IF_TO_BE_ACTIVATED)) @@ -229,26 +232,39 @@ static void hardif_deactivate_interface(struct net_device *net_dev,
batman_if->if_status = IF_INACTIVE;
- bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev); + bat_info(batman_if->soft_iface, "Interface deactivated: %s\n", + batman_if->dev);
- update_min_mtu(); + update_min_mtu(batman_if->soft_iface); }
-int hardif_enable_interface(struct batman_if *batman_if) +int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv; struct batman_packet *batman_packet;
if (batman_if->if_status != IF_NOT_IN_USE) goto out;
+ batman_if->soft_iface = dev_get_by_name(&init_net, iface_name); + + if (!batman_if->soft_iface) { + batman_if->soft_iface = softif_create(iface_name); + + if (!batman_if->soft_iface) + goto err; + + /* dev_get_by_name() increases the reference counter for us */ + dev_hold(batman_if->soft_iface); + } + + bat_priv = netdev_priv(batman_if->soft_iface); batman_if->packet_len = BAT_PACKET_LEN; batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
if (!batman_if->packet_buff) { - bat_err(soft_device, "Can't add interface packet (%s): " - "out of memory\n", batman_if->dev); + bat_err(batman_if->soft_iface, "Can't add interface packet " + "(%s): out of memory\n", batman_if->dev); goto err; }
@@ -272,11 +288,12 @@ int hardif_enable_interface(struct batman_if *batman_if)
atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->frag_seqno, 1); - bat_info(soft_device, "Adding interface: %s\n", batman_if->dev); + bat_info(batman_if->soft_iface, "Adding interface: %s\n", + batman_if->dev);
if (atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < ETH_DATA_LEN + BAT_HEADER_LEN) - bat_info(soft_device, + bat_info(batman_if->soft_iface, "The MTU of interface %s is too small (%i) to handle " "the transport of batman-adv packets. Packets going " "over this interface will be fragmented on layer2 " @@ -287,7 +304,7 @@ int hardif_enable_interface(struct batman_if *batman_if)
if (!atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < ETH_DATA_LEN + BAT_HEADER_LEN) - bat_info(soft_device, + bat_info(batman_if->soft_iface, "The MTU of interface %s is too small (%i) to handle " "the transport of batman-adv packets. If you experience" " problems getting traffic through try increasing the " @@ -296,9 +313,9 @@ int hardif_enable_interface(struct batman_if *batman_if) ETH_DATA_LEN + BAT_HEADER_LEN);
if (hardif_is_iface_up(batman_if)) - hardif_activate_interface(soft_device, bat_priv, batman_if); + hardif_activate_interface(batman_if); else - bat_err(soft_device, "Not using interface %s " + bat_err(batman_if->soft_iface, "Not using interface %s " "(retrying later): interface not active\n", batman_if->dev);
@@ -314,16 +331,16 @@ err:
void hardif_disable_interface(struct batman_if *batman_if) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
if (batman_if->if_status == IF_ACTIVE) - hardif_deactivate_interface(soft_device, batman_if); + hardif_deactivate_interface(batman_if);
if (batman_if->if_status != IF_INACTIVE) return;
- bat_info(soft_device, "Removing interface: %s\n", batman_if->dev); + bat_info(batman_if->soft_iface, "Removing interface: %s\n", + batman_if->dev); dev_remove_pack(&batman_if->batman_adv_ptype);
bat_priv->num_ifaces--; @@ -335,10 +352,17 @@ void hardif_disable_interface(struct batman_if *batman_if) kfree(batman_if->packet_buff); batman_if->packet_buff = NULL; batman_if->if_status = IF_NOT_IN_USE; + dev_put(batman_if->soft_iface);
- if ((atomic_read(&module_state) == MODULE_ACTIVE) && + /* nobody uses this interface anymore */ + if (!bat_priv->num_ifaces) + softif_destroy(batman_if->soft_iface); + + batman_if->soft_iface = NULL; + + /*if ((atomic_read(&module_state) == MODULE_ACTIVE) && (bat_priv->num_ifaces == 0)) - deactivate_module(); + deactivate_module();*/ }
static struct batman_if *hardif_add_interface(struct net_device *net_dev) @@ -369,8 +393,8 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
batman_if->if_num = -1; batman_if->net_dev = net_dev; + batman_if->soft_iface = NULL; batman_if->if_status = IF_NOT_IN_USE; - batman_if->packet_buff = NULL; INIT_LIST_HEAD(&batman_if->list);
check_known_mac_addr(batman_if->net_dev->dev_addr); @@ -419,8 +443,11 @@ void hardif_remove_interfaces(void) { struct batman_if *batman_if, *batman_if_tmp;
- list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) + list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) { + rtnl_lock(); hardif_remove_interface(batman_if); + rtnl_unlock(); + } }
static int hard_if_event(struct notifier_block *this, @@ -428,8 +455,7 @@ static int hard_if_event(struct notifier_block *this, { 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); + struct bat_priv *bat_priv;
if (!batman_if && event == NETDEV_REGISTER) batman_if = hardif_add_interface(net_dev); @@ -439,11 +465,11 @@ static int hard_if_event(struct notifier_block *this,
switch (event) { case NETDEV_UP: - hardif_activate_interface(soft_device, bat_priv, batman_if); + hardif_activate_interface(batman_if); break; case NETDEV_GOING_DOWN: case NETDEV_DOWN: - hardif_deactivate_interface(soft_device, batman_if); + hardif_deactivate_interface(batman_if); break; case NETDEV_UNREGISTER: hardif_remove_interface(batman_if); @@ -451,8 +477,13 @@ static int hard_if_event(struct notifier_block *this, case NETDEV_CHANGENAME: break; case NETDEV_CHANGEADDR: + if (batman_if->if_status == IF_NOT_IN_USE) + goto out; + check_known_mac_addr(batman_if->net_dev->dev_addr); update_mac_addresses(batman_if); + + bat_priv = netdev_priv(batman_if->soft_iface); if (batman_if == bat_priv->primary_if) set_primary_if(bat_priv, batman_if); break; @@ -469,8 +500,7 @@ out: int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv; struct batman_packet *batman_packet; struct batman_if *batman_if; int ret; @@ -499,6 +529,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, goto err_free;
batman_packet = (struct batman_packet *)skb->data; + bat_priv = netdev_priv(batman_if->soft_iface);
if (batman_packet->version != COMPAT_VERSION) { bat_dbg(DBG_BATMAN, bat_priv, @@ -518,7 +549,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
/* batman icmp packet */ case BAT_ICMP: - ret = recv_icmp_packet(skb); + ret = recv_icmp_packet(skb, batman_if); break;
/* unicast packet */ @@ -533,12 +564,12 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
/* broadcast packet */ case BAT_BCAST: - ret = recv_bcast_packet(skb); + ret = recv_bcast_packet(skb, batman_if); break;
/* vis packet */ case BAT_VIS: - ret = recv_vis_packet(skb); + ret = recv_vis_packet(skb, batman_if); break; default: ret = NET_RX_DROP; diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h index d5640b0..4b49527 100644 --- a/drivers/staging/batman-adv/hard-interface.h +++ b/drivers/staging/batman-adv/hard-interface.h @@ -32,14 +32,14 @@ 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); +int hardif_enable_interface(struct batman_if *batman_if, char *iface_name); void hardif_disable_interface(struct batman_if *batman_if); void hardif_remove_interfaces(void); int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev); -int hardif_min_mtu(void); -void update_min_mtu(void); +int hardif_min_mtu(struct net_device *soft_iface); +void update_min_mtu(struct net_device *soft_iface);
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c index 1286f8f..8ef26eb 100644 --- a/drivers/staging/batman-adv/hash.c +++ b/drivers/staging/batman-adv/hash.c @@ -36,7 +36,7 @@ static void hash_init(struct hashtable_t *hash) /* remove the hash structure. if hashdata_free_cb != NULL, this function will be * called to remove the elements inside of the hash. if you don't remove the * elements, memory might be leaked. */ -void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb) +void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb, void *arg) { struct element_t *bucket, *last_bucket; int i; @@ -46,7 +46,7 @@ void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb)
while (bucket != NULL) { if (free_cb != NULL) - free_cb(bucket->data); + free_cb(bucket->data, arg);
last_bucket = bucket; bucket = bucket->next; @@ -300,7 +300,7 @@ struct hashtable_t *hash_resize(struct hashtable_t *hash, int size)
/* remove hash and eventual overflow buckets but not the content * itself. */ - hash_delete(hash, NULL); + hash_delete(hash, NULL, NULL);
return new_hash; } diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h index c483e11..2c8e176 100644 --- a/drivers/staging/batman-adv/hash.h +++ b/drivers/staging/batman-adv/hash.h @@ -30,7 +30,7 @@
typedef int (*hashdata_compare_cb)(void *, void *); typedef int (*hashdata_choose_cb)(void *, int); -typedef void (*hashdata_free_cb)(void *); +typedef void (*hashdata_free_cb)(void *, void *);
struct element_t { void *data; /* pointer to the data */ @@ -70,7 +70,7 @@ void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t); /* remove the hash structure. if hashdata_free_cb != NULL, this function will be * called to remove the elements inside of the hash. if you don't remove the * elements, memory might be leaked. */ -void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb); +void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb, void *arg);
/* free only the hashtable and the hash itself. */ void hash_destroy(struct hashtable_t *hash); diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index 8e986a1..2a1d3dd 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -156,6 +156,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, struct bat_priv *bat_priv = socket_client->bat_priv; struct sk_buff *skb; struct icmp_packet_rr *icmp_packet; + struct orig_node *orig_node; struct batman_if *batman_if; size_t packet_len = sizeof(struct icmp_packet); diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index eb0bfbe..52c019b 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -44,8 +44,6 @@ DEFINE_SPINLOCK(forw_bcast_list_lock);
int16_t num_hna;
-struct net_device *soft_device; - unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; atomic_t module_state;
@@ -53,8 +51,6 @@ struct workqueue_struct *bat_event_workqueue;
static int __init batman_init(void) { - int retval; - INIT_LIST_HEAD(&if_list); INIT_HLIST_HEAD(&forw_bat_list); INIT_HLIST_HEAD(&forw_bcast_list); @@ -71,32 +67,6 @@ static int __init batman_init(void) bat_socket_init(); debugfs_init();
- /* initialize layer 2 interface */ - soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", - interface_setup); - - if (!soft_device) { - pr_err("Unable to allocate the batman interface\n"); - goto end; - } - - retval = register_netdev(soft_device); - - if (retval < 0) { - pr_err("Unable to register the batman interface: %i\n", retval); - goto free_soft_device; - } - - retval = sysfs_add_meshif(soft_device); - - if (retval < 0) - goto unreg_soft_device; - - retval = debugfs_add_meshif(soft_device); - - if (retval < 0) - goto unreg_sysfs; - register_netdevice_notifier(&hard_if_notifier);
pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) " @@ -104,19 +74,6 @@ static int __init batman_init(void) COMPAT_VERSION);
return 0; - -unreg_sysfs: - sysfs_del_meshif(soft_device); -unreg_soft_device: - unregister_netdev(soft_device); - soft_device = NULL; - return -ENOMEM; - -free_soft_device: - free_netdev(soft_device); - soft_device = NULL; -end: - return -ENOMEM; }
static void __exit batman_exit(void) @@ -127,13 +84,6 @@ static void __exit batman_exit(void) unregister_netdevice_notifier(&hard_if_notifier); hardif_remove_interfaces();
- if (soft_device) { - debugfs_del_meshif(soft_device); - sysfs_del_meshif(soft_device); - unregister_netdev(soft_device); - soft_device = NULL; - } - destroy_workqueue(bat_event_workqueue); bat_event_workqueue = NULL; } @@ -150,12 +100,12 @@ void activate_module(void) if (hna_global_init() < 1) goto err;
- hna_local_add(soft_device->dev_addr); + /*hna_local_add(soft_device->dev_addr);*/
if (vis_init() < 1) goto err;
- update_min_mtu(); + /*update_min_mtu();*/ atomic_set(&module_state, MODULE_ACTIVE); goto end;
diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 2d364e0..2309d82 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -138,8 +138,6 @@ extern spinlock_t forw_bcast_list_lock;
extern int16_t num_hna;
-extern struct net_device *soft_device; - extern unsigned char broadcast_addr[]; extern atomic_t module_state; extern struct workqueue_struct *bat_event_workqueue; diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index b51a13e..7ed3266 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -61,8 +61,7 @@ struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct neigh_node *neigh_node;
bat_dbg(DBG_BATMAN, bat_priv, @@ -82,11 +81,12 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, return neigh_node; }
-static void free_orig_node(void *data) +static void free_orig_node(void *data, void *arg) { struct list_head *list_pos, *list_pos_tmp; struct neigh_node *neigh_node; struct orig_node *orig_node = (struct orig_node *)data; + struct bat_priv *bat_priv = (struct bat_priv *)arg;
/* for all neighbors towards this originator ... */ list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { @@ -97,7 +97,7 @@ static void free_orig_node(void *data) }
frag_list_free(&orig_node->frag_list); - hna_global_del_orig(orig_node, "originator timed out"); + hna_global_del_orig(bat_priv, orig_node, "originator timed out");
kfree(orig_node->bcast_own); kfree(orig_node->bcast_own_sum); @@ -114,17 +114,15 @@ void originator_free(void) cancel_delayed_work_sync(&purge_orig_wq);
spin_lock_irqsave(&orig_hash_lock, flags); - hash_delete(orig_hash, free_orig_node); + /*hash_delete(orig_hash, free_orig_node, bat_priv);*/ orig_hash = NULL; spin_unlock_irqrestore(&orig_hash_lock, flags); }
/* this function finds or creates an originator entry for the given * address if it does not exits */ -struct orig_node *get_orig_node(uint8_t *addr) +struct orig_node *get_orig_node(struct bat_priv *bat_priv, 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; @@ -173,7 +171,7 @@ struct orig_node *get_orig_node(uint8_t *addr) swaphash = hash_resize(orig_hash, orig_hash->size * 2);
if (swaphash == NULL) - bat_err(soft_device, + bat_dbg(DBG_BATMAN, bat_priv, "Couldn't resize orig hash table\n"); else orig_hash = swaphash; @@ -189,11 +187,10 @@ free_orig_node: return NULL; }
-static bool purge_orig_neighbors(struct orig_node *orig_node, +static bool purge_orig_neighbors(struct bat_priv *bat_priv, + struct orig_node *orig_node, struct neigh_node **best_neigh_node) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); struct list_head *list_pos, *list_pos_tmp; struct neigh_node *neigh_node; bool neigh_purged = false; @@ -235,10 +232,9 @@ static bool purge_orig_neighbors(struct orig_node *orig_node, return neigh_purged; }
-static bool purge_orig_node(struct orig_node *orig_node) +static bool purge_orig_node(struct bat_priv *bat_priv, + struct orig_node *orig_node) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); struct neigh_node *best_neigh_node;
if (time_after(jiffies, @@ -249,8 +245,10 @@ static bool purge_orig_node(struct orig_node *orig_node) orig_node->orig, (orig_node->last_valid / HZ)); return true; } else { - if (purge_orig_neighbors(orig_node, &best_neigh_node)) { - update_routes(orig_node, best_neigh_node, + if (purge_orig_neighbors(bat_priv, orig_node, + &best_neigh_node)) { + update_routes(bat_priv, orig_node, + best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len); /* update bonding candidates, we could have lost @@ -273,13 +271,14 @@ void purge_orig(struct work_struct *work) /* for all origins... */ while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; - if (purge_orig_node(orig_node)) { + + /*if (purge_orig_node(bat_priv, orig_node)) { hash_remove_bucket(orig_hash, &hashit); free_orig_node(orig_node); - } + }*/
if (time_after(jiffies, (orig_node->last_frag_packet + - msecs_to_jiffies(FRAG_TIMEOUT)))) + msecs_to_jiffies(FRAG_TIMEOUT)))) frag_list_free(&orig_node->frag_list); }
diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h index e88411d..bc47c68 100644 --- a/drivers/staging/batman-adv/originator.h +++ b/drivers/staging/batman-adv/originator.h @@ -25,7 +25,7 @@ int originator_init(void); void originator_free(void); void purge_orig(struct work_struct *work); -struct orig_node *get_orig_node(uint8_t *addr); +struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming); diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 6009adc..3cae7c4 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -38,6 +38,7 @@ static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
void slide_own_bcast_window(struct batman_if *batman_if) { + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); HASHIT(hashit); struct orig_node *orig_node; TYPE_OF_WORD *word; @@ -49,7 +50,7 @@ void slide_own_bcast_window(struct batman_if *batman_if) orig_node = hashit.bucket->data; word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
- bit_get_packet(word, 1, 0); + bit_get_packet(bat_priv, word, 1, 0); orig_node->bcast_own_sum[batman_if->if_num] = bit_packet_count(word); } @@ -57,7 +58,7 @@ void slide_own_bcast_window(struct batman_if *batman_if) spin_unlock_irqrestore(&orig_hash_lock, flags); }
-static void update_HNA(struct orig_node *orig_node, +static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len) { if ((hna_buff_len != orig_node->hna_buff_len) || @@ -66,27 +67,27 @@ static void update_HNA(struct orig_node *orig_node, (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
if (orig_node->hna_buff_len > 0) - hna_global_del_orig(orig_node, + hna_global_del_orig(bat_priv, orig_node, "originator changed hna");
if ((hna_buff_len > 0) && (hna_buff != NULL)) - hna_global_add_orig(orig_node, hna_buff, hna_buff_len); + hna_global_add_orig(bat_priv, orig_node, + hna_buff, hna_buff_len); } }
-static void update_route(struct orig_node *orig_node, +static void update_route(struct bat_priv *bat_priv, + struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); - /* route deleted */ if ((orig_node->router != NULL) && (neigh_node == NULL)) {
bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", orig_node->orig); - hna_global_del_orig(orig_node, "originator timed out"); + hna_global_del_orig(bat_priv, orig_node, + "originator timed out");
/* route added */ } else if ((orig_node->router == NULL) && (neigh_node != NULL)) { @@ -94,7 +95,8 @@ static void update_route(struct orig_node *orig_node, bat_dbg(DBG_ROUTES, bat_priv, "Adding route towards: %pM (via %pM)\n", orig_node->orig, neigh_node->addr); - hna_global_add_orig(orig_node, hna_buff, hna_buff_len); + hna_global_add_orig(bat_priv, orig_node, + hna_buff, hna_buff_len);
/* route changed */ } else { @@ -109,19 +111,20 @@ static void update_route(struct orig_node *orig_node, }
-void update_routes(struct orig_node *orig_node, - struct neigh_node *neigh_node, - unsigned char *hna_buff, int hna_buff_len) +void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, + struct neigh_node *neigh_node, unsigned char *hna_buff, + int hna_buff_len) {
if (orig_node == NULL) return;
if (orig_node->router != neigh_node) - update_route(orig_node, neigh_node, hna_buff, hna_buff_len); + update_route(bat_priv, orig_node, neigh_node, + hna_buff, hna_buff_len); /* may be just HNA changed */ else - update_HNA(orig_node, hna_buff, hna_buff_len); + update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); }
static int is_bidirectional_neigh(struct orig_node *orig_node, @@ -129,8 +132,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, struct batman_packet *batman_packet, struct batman_if *if_incoming) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; unsigned char total_count;
@@ -234,14 +236,14 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, return 0; }
-static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, +static void update_orig(struct bat_priv *bat_priv, + struct orig_node *orig_node, + struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming, unsigned char *hna_buff, int hna_buff_len, char is_duplicate) { - /* FIXME: get bat_priv */ - struct bat_priv *bat_priv = netdev_priv(soft_device); struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; int tmp_hna_buff_len;
@@ -267,12 +269,11 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, if (!neigh_node) { struct orig_node *orig_tmp;
- orig_tmp = get_orig_node(ethhdr->h_source); + orig_tmp = get_orig_node(bat_priv, ethhdr->h_source); if (!orig_tmp) return;
- neigh_node = create_neighbor(orig_node, - orig_tmp, + neigh_node = create_neighbor(orig_node, orig_tmp, ethhdr->h_source, if_incoming); if (!neigh_node) return; @@ -314,11 +315,13 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, >= neigh_node->orig_node->bcast_own_sum[if_incoming->if_num]))) goto update_hna;
- update_routes(orig_node, neigh_node, hna_buff, tmp_hna_buff_len); + update_routes(bat_priv, orig_node, neigh_node, + hna_buff, tmp_hna_buff_len); return;
update_hna: - update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len); + update_routes(bat_priv, orig_node, orig_node->router, + hna_buff, tmp_hna_buff_len); }
/* checks whether the host restarted and is in the protection time. @@ -326,12 +329,10 @@ update_hna: * 0 if the packet is to be accepted * 1 if the packet is to be ignored. */ -static int window_protected(int32_t seq_num_diff, - unsigned long *last_reset) +static int window_protected(struct bat_priv *bat_priv, + int32_t seq_num_diff, + unsigned long *last_reset) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); - if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { if (time_after(jiffies, *last_reset + @@ -360,8 +361,7 @@ static char count_real_packets(struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct orig_node *orig_node; struct neigh_node *tmp_neigh_node; char is_duplicate = 0; @@ -369,14 +369,15 @@ static char count_real_packets(struct ethhdr *ethhdr, int need_update = 0; int set_mark;
- orig_node = get_orig_node(batman_packet->orig); + orig_node = get_orig_node(bat_priv, batman_packet->orig); if (orig_node == NULL) return 0;
seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
/* signalize caller that the packet is to be dropped. */ - if (window_protected(seq_diff, &orig_node->batman_seqno_reset)) + if (window_protected(bat_priv, seq_diff, + &orig_node->batman_seqno_reset)) return -1;
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { @@ -392,8 +393,9 @@ static char count_real_packets(struct ethhdr *ethhdr, set_mark = 0;
/* if the window moved, set the update flag. */ - need_update |= bit_get_packet(tmp_neigh_node->real_bits, - seq_diff, set_mark); + need_update |= bit_get_packet(bat_priv, + tmp_neigh_node->real_bits, + seq_diff, set_mark);
tmp_neigh_node->real_packet_count = bit_packet_count(tmp_neigh_node->real_bits); @@ -521,8 +523,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct batman_if *batman_if; struct orig_node *orig_neigh_node, *orig_node; char has_directlink_flag; @@ -609,7 +610,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, TYPE_OF_WORD *word; int offset;
- orig_neigh_node = get_orig_node(ethhdr->h_source); + orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
if (!orig_neigh_node) return; @@ -641,7 +642,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, return; }
- orig_node = get_orig_node(batman_packet->orig); + orig_node = get_orig_node(bat_priv, batman_packet->orig); if (orig_node == NULL) return;
@@ -677,7 +678,8 @@ void receive_bat_packet(struct ethhdr *ethhdr, /* if sender is a direct neighbor the sender mac equals * originator mac */ orig_neigh_node = (is_single_hop_neigh ? - orig_node : get_orig_node(ethhdr->h_source)); + orig_node : + get_orig_node(bat_priv, ethhdr->h_source)); if (orig_neigh_node == NULL) return;
@@ -699,7 +701,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, (!is_duplicate || ((orig_node->last_real_seqno == batman_packet->seqno) && (orig_node->last_ttl - 3 <= batman_packet->ttl)))) - update_orig(orig_node, ethhdr, batman_packet, + update_orig(bat_priv, orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate);
mark_bonding_address(bat_priv, orig_node, @@ -778,10 +780,11 @@ int recv_bat_packet(struct sk_buff *skb, return NET_RX_SUCCESS; }
-static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) +static int recv_my_icmp_packet(struct sk_buff *skb, + struct batman_if *recv_if, size_t icmp_len) { /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; @@ -840,10 +843,11 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) return ret; }
-static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) +static int recv_icmp_ttl_exceeded(struct sk_buff *skb, + struct batman_if *recv_if, size_t icmp_len) { /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; struct icmp_packet *icmp_packet; struct ethhdr *ethhdr; @@ -904,7 +908,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) }
-int recv_icmp_packet(struct sk_buff *skb) +int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if) { struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; @@ -951,11 +955,11 @@ int recv_icmp_packet(struct sk_buff *skb)
/* packet for me */ if (is_my_mac(icmp_packet->dst)) - return recv_my_icmp_packet(skb, hdr_size); + return recv_my_icmp_packet(skb, recv_if, hdr_size);
/* TTL exceeded */ if (icmp_packet->ttl < 2) - return recv_icmp_ttl_exceeded(skb, hdr_size); + return recv_icmp_ttl_exceeded(skb, recv_if, hdr_size);
ret = NET_RX_DROP;
@@ -996,10 +1000,9 @@ int recv_icmp_packet(struct sk_buff *skb) /* find a suitable router for this originator, and use * bonding if possible. */ struct neigh_node *find_router(struct orig_node *orig_node, - struct batman_if *recv_if) + struct batman_if *recv_if) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv; struct orig_node *primary_orig_node; struct orig_node *router_orig; struct neigh_node *router, *first_candidate, *best_router; @@ -1015,9 +1018,14 @@ struct neigh_node *find_router(struct orig_node *orig_node, /* without bonding, the first node should * always choose the default router. */
+ if (!recv_if) + return orig_node->router; + + bat_priv = netdev_priv(recv_if->soft_iface); bonding_enabled = atomic_read(&bat_priv->bonding_enabled); - if (!bonding_enabled && (recv_if == NULL)) - return orig_node->router; + + if (!bonding_enabled) + return orig_node->router;
router_orig = orig_node->router->orig_node;
@@ -1094,7 +1102,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) if (unlikely(!pskb_may_pull(skb, hdr_size))) return -1;
- ethhdr = (struct ethhdr *) skb_mac_header(skb); + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */ if (is_bcast(ethhdr->h_dest)) @@ -1111,17 +1119,24 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) return 0; }
-static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, - int hdr_size) +static int route_unicast_packet(struct sk_buff *skb, + struct batman_if *recv_if, int hdr_size) { struct orig_node *orig_node; struct neigh_node *router; struct batman_if *batman_if; uint8_t dstaddr[ETH_ALEN]; unsigned long flags; - struct unicast_packet *unicast_packet = - (struct unicast_packet *) skb->data; - struct ethhdr *ethhdr = (struct ethhdr *) skb_mac_header(skb); + struct unicast_packet *unicast_packet; + struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); + + unicast_packet = (struct unicast_packet *)skb->data; + + /* packet for me */ + if (is_my_mac(unicast_packet->dest)) { + interface_rx(recv_if->soft_iface, skb, hdr_size); + return NET_RX_SUCCESS; + }
/* TTL exceeded */ if (unicast_packet->ttl < 2) { @@ -1175,11 +1190,11 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) if (check_unicast_packet(skb, hdr_size) < 0) return NET_RX_DROP;
- unicast_packet = (struct unicast_packet *) skb->data; + unicast_packet = (struct unicast_packet *)skb->data;
/* packet for me */ if (is_my_mac(unicast_packet->dest)) { - interface_rx(skb, hdr_size); + interface_rx(recv_if->soft_iface, skb, hdr_size); return NET_RX_SUCCESS; }
@@ -1234,18 +1249,20 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) if (!skb) return NET_RX_DROP;
- interface_rx(skb, hdr_size); + interface_rx(recv_if->soft_iface, skb, hdr_size); return NET_RX_SUCCESS; }
return route_unicast_packet(skb, recv_if, hdr_size); }
-int recv_bcast_packet(struct sk_buff *skb) + +int recv_bcast_packet(struct sk_buff *skb, struct batman_if *batman_if) { struct orig_node *orig_node; struct bcast_packet *bcast_packet; struct ethhdr *ethhdr; + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); int hdr_size = sizeof(struct bcast_packet); int32_t seq_diff; unsigned long flags; @@ -1297,31 +1314,32 @@ int recv_bcast_packet(struct sk_buff *skb) seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
/* check whether the packet is old and the host just restarted. */ - if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) { + if (window_protected(bat_priv, seq_diff, + &orig_node->bcast_seqno_reset)) { spin_unlock_irqrestore(&orig_hash_lock, flags); return NET_RX_DROP; }
/* mark broadcast in flood history, update window position * if required. */ - if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1)) + if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1)) orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
spin_unlock_irqrestore(&orig_hash_lock, flags); /* rebroadcast packet */ - add_bcast_packet_to_list(skb); + add_bcast_packet_to_list(bat_priv, skb);
/* broadcast for me */ - interface_rx(skb, hdr_size); + interface_rx(batman_if->soft_iface, skb, hdr_size);
return NET_RX_SUCCESS; }
-int recv_vis_packet(struct sk_buff *skb) +int recv_vis_packet(struct sk_buff *skb, struct batman_if *batman_if) { struct vis_packet *vis_packet; struct ethhdr *ethhdr; - struct bat_priv *bat_priv; + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); int hdr_size = sizeof(struct vis_packet);
/* keep skb linear */ @@ -1331,7 +1349,7 @@ int recv_vis_packet(struct sk_buff *skb) if (unlikely(!pskb_may_pull(skb, hdr_size))) return NET_RX_DROP;
- vis_packet = (struct vis_packet *) skb->data; + vis_packet = (struct vis_packet *)skb->data; ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* not for me */ @@ -1345,9 +1363,6 @@ int recv_vis_packet(struct sk_buff *skb) if (is_my_mac(vis_packet->sender_orig)) return NET_RX_DROP;
- /* FIXME: each batman_if will be attached to a softif */ - bat_priv = netdev_priv(soft_device); - switch (vis_packet->vis_type) { case VIS_TYPE_SERVER_SYNC: receive_server_sync_packet(bat_priv, vis_packet, diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 81c684f..55995e4 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -29,14 +29,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming); -void update_routes(struct orig_node *orig_node, - struct neigh_node *neigh_node, - unsigned char *hna_buff, int hna_buff_len); -int recv_icmp_packet(struct sk_buff *skb); +void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, + struct neigh_node *neigh_node, unsigned char *hna_buff, + int hna_buff_len); +int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); -int recv_bcast_packet(struct sk_buff *skb); -int recv_vis_packet(struct sk_buff *skb); +int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if); +int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if); struct neigh_node *find_router(struct orig_node *orig_node, diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index aebd6c3..3505d1b 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -103,8 +103,7 @@ send_skb_err: static void send_packet_to_if(struct forw_packet *forw_packet, struct batman_if *batman_if) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); char *fwd_str; uint8_t packet_num; int16_t buff_pos; @@ -160,9 +159,9 @@ static void send_packet_to_if(struct forw_packet *forw_packet, /* send a batman packet */ static void send_packet(struct forw_packet *forw_packet) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); struct batman_if *batman_if; + struct bat_priv *bat_priv = + netdev_priv(forw_packet->if_incoming->soft_iface); struct batman_packet *batman_packet = (struct batman_packet *)(forw_packet->skb->data); unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0); @@ -232,8 +231,7 @@ static void rebuild_batman_packet(struct batman_if *batman_if)
void schedule_own_packet(struct batman_if *batman_if) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); unsigned long send_time; struct batman_packet *batman_packet; int vis_server; @@ -290,8 +288,7 @@ void schedule_forward_packet(struct orig_node *orig_node, uint8_t directlink, int hna_buff_len, struct batman_if *if_incoming) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); unsigned char in_tq, in_ttl, tq_avg = 0; unsigned long send_time;
@@ -381,12 +378,10 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, * * The skb is not consumed, so the caller should make sure that the * skb is freed. */ -int add_bcast_packet_to_list(struct sk_buff *skb) +int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) { struct forw_packet *forw_packet; struct bcast_packet *bcast_packet; - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device);
if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) { bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n"); @@ -409,6 +404,7 @@ int add_bcast_packet_to_list(struct sk_buff *skb) skb_reset_mac_header(skb);
forw_packet->skb = skb; + forw_packet->if_incoming = bat_priv->primary_if;
/* how often did we send the bcast packet ? */ forw_packet->num_packets = 0; @@ -433,8 +429,7 @@ static void send_outstanding_bcast_packet(struct work_struct *work) container_of(delayed_work, struct forw_packet, delayed_work); unsigned long flags; struct sk_buff *skb1; - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv;
spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_del(&forw_packet->list); @@ -463,6 +458,7 @@ static void send_outstanding_bcast_packet(struct work_struct *work) }
out: + bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); forw_packet_free(forw_packet); atomic_inc(&bat_priv->bcast_queue_left); } @@ -474,8 +470,7 @@ void send_outstanding_bat_packet(struct work_struct *work) struct forw_packet *forw_packet = container_of(delayed_work, struct forw_packet, delayed_work); unsigned long flags; - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv;
spin_lock_irqsave(&forw_bat_list_lock, flags); hlist_del(&forw_packet->list); @@ -495,6 +490,8 @@ void send_outstanding_bat_packet(struct work_struct *work) schedule_own_packet(forw_packet->if_incoming);
out: + bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); + /* don't count own packet */ if (!forw_packet->own) atomic_inc(&bat_priv->batman_queue_left); @@ -504,19 +501,22 @@ out:
void purge_outstanding_packets(struct batman_if *batman_if) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv; struct forw_packet *forw_packet; struct hlist_node *tmp_node, *safe_tmp_node; unsigned long flags;
- if (batman_if) - bat_dbg(DBG_BATMAN, bat_priv, - "purge_outstanding_packets(): %s\n", - batman_if->dev); - else - bat_dbg(DBG_BATMAN, bat_priv, - "purge_outstanding_packets()\n"); + if (batman_if->soft_iface) { + bat_priv = netdev_priv(batman_if->soft_iface); + + if (batman_if) + bat_dbg(DBG_BATMAN, bat_priv, + "purge_outstanding_packets(): %s\n", + batman_if->dev); + else + bat_dbg(DBG_BATMAN, bat_priv, + "purge_outstanding_packets()\n"); + }
/* free bcast list */ spin_lock_irqsave(&forw_bcast_list_lock, flags); diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h index 0cfe027..39a3426 100644 --- a/drivers/staging/batman-adv/send.h +++ b/drivers/staging/batman-adv/send.h @@ -33,7 +33,7 @@ void schedule_forward_packet(struct orig_node *orig_node, struct batman_packet *batman_packet, uint8_t directlink, int hna_buff_len, struct batman_if *if_outgoing); -int add_bcast_packet_to_list(struct sk_buff *skb); +int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); void send_outstanding_bat_packet(struct work_struct *work); void purge_outstanding_packets(struct batman_if *batman_if);
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index e8be209..864f85d 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -22,8 +22,14 @@ #include "main.h" #include "soft-interface.h" #include "hard-interface.h" +#include "routing.h" +#include "send.h" +#include "bat_debugfs.h" #include "translation-table.h" +#include "types.h" +#include "hash.h" #include "send.h" +#include "bat_sysfs.h" #include <linux/slab.h> #include <linux/ethtool.h> #include <linux/etherdevice.h> @@ -92,12 +98,13 @@ static int interface_release(struct net_device *dev)
static struct net_device_stats *interface_stats(struct net_device *dev) { - struct bat_priv *priv = netdev_priv(dev); - return &priv->stats; + struct bat_priv *bat_priv = netdev_priv(dev); + return &bat_priv->stats; }
static int interface_set_mac_addr(struct net_device *dev, void *p) { + struct bat_priv *bat_priv = netdev_priv(dev); struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data)) @@ -105,8 +112,9 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
/* only modify hna-table if it has been initialised before */ if (atomic_read(&module_state) == MODULE_ACTIVE) { - hna_local_remove(dev->dev_addr, "mac address changed"); - hna_local_add(addr->sa_data); + hna_local_remove(bat_priv, dev->dev_addr, + "mac address changed"); + hna_local_add(dev, addr->sa_data); }
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -117,7 +125,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) static int interface_change_mtu(struct net_device *dev, int new_mtu) { /* check ranges */ - if ((new_mtu < 68) || (new_mtu > hardif_min_mtu())) + if ((new_mtu < 68) || (new_mtu > hardif_min_mtu(dev))) return -EINVAL;
dev->mtu = new_mtu; @@ -125,19 +133,20 @@ static int interface_change_mtu(struct net_device *dev, int new_mtu) return 0; }
-int interface_tx(struct sk_buff *skb, struct net_device *dev) +int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) { struct ethhdr *ethhdr = (struct ethhdr *)skb->data; - struct bat_priv *bat_priv = netdev_priv(dev); + struct bat_priv *bat_priv = netdev_priv(soft_iface); struct bcast_packet *bcast_packet; int data_len = skb->len, ret;
if (atomic_read(&module_state) != MODULE_ACTIVE) goto dropped;
- dev->trans_start = jiffies; + soft_iface->trans_start = jiffies; + /* TODO: check this for locks */ - hna_local_add(ethhdr->h_source); + hna_local_add(soft_iface, ethhdr->h_source);
/* ethernet packet should be broadcasted */ if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) { @@ -160,7 +169,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) bcast_packet->seqno = htonl(bcast_seqno);
/* broadcast packet. on success, increase seqno. */ - if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK) + if (add_bcast_packet_to_list(bat_priv, skb) == NETDEV_TX_OK) bcast_seqno++;
/* a copy is stored in the bcast list, therefore removing @@ -187,10 +196,10 @@ end: return NETDEV_TX_OK; }
-void interface_rx(struct sk_buff *skb, int hdr_size) +void interface_rx(struct net_device *soft_iface, + struct sk_buff *skb, int hdr_size) { - struct net_device *dev = soft_device; - struct bat_priv *priv = netdev_priv(dev); + struct bat_priv *priv = netdev_priv(soft_iface);
/* check if enough space is available for pulling, and pull */ if (!pskb_may_pull(skb, hdr_size)) { @@ -200,8 +209,8 @@ void interface_rx(struct sk_buff *skb, int hdr_size) skb_pull_rcsum(skb, hdr_size); /* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
- skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); + skb->dev = soft_iface; + skb->protocol = eth_type_trans(skb, soft_iface);
/* should not be neccesary anymore as we use skb_pull_rcsum() * TODO: please verify this and remove this TODO @@ -215,7 +224,7 @@ void interface_rx(struct sk_buff *skb, int hdr_size) priv->stats.rx_packets++; priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
- dev->last_rx = jiffies; + soft_iface->last_rx = jiffies;
netif_rx(skb); } @@ -232,7 +241,7 @@ static const struct net_device_ops bat_netdev_ops = { }; #endif
-void interface_setup(struct net_device *dev) +static void interface_setup(struct net_device *dev) { struct bat_priv *priv = netdev_priv(dev); char dev_addr[ETH_ALEN]; @@ -251,9 +260,11 @@ void interface_setup(struct net_device *dev) #endif dev->destructor = free_netdev;
- dev->mtu = ETH_DATA_LEN; /* can't call min_mtu, because the - * needed variables have not been - * initialized yet */ + /** + * can't call min_mtu, because the needed variables + * have not been initialized yet + */ + dev->mtu = ETH_DATA_LEN; dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the * skbuff for our header */
@@ -266,6 +277,73 @@ void interface_setup(struct net_device *dev) memset(priv, 0, sizeof(struct bat_priv)); }
+struct net_device *softif_create(char *name) +{ + struct net_device *soft_iface; + struct bat_priv *bat_priv; + int ret; + + soft_iface = alloc_netdev(sizeof(struct bat_priv) , name, + interface_setup); + + if (!soft_iface) { + pr_err("Unable to allocate the batman interface: %s\n", name); + goto out; + } + + ret = register_netdev(soft_iface); + + if (ret < 0) { + pr_err("Unable to register the batman interface '%s': %i\n", + name, ret); + goto free_soft_iface; + } + + bat_priv = netdev_priv(soft_iface); + + atomic_set(&bat_priv->aggregation_enabled, 1); + atomic_set(&bat_priv->bonding_enabled, 0); + atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); + atomic_set(&bat_priv->orig_interval, 1000); + atomic_set(&bat_priv->log_level, 0); + atomic_set(&bat_priv->frag_enabled, 1); + atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN); + atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN); + + bat_priv->primary_if = NULL; + bat_priv->num_ifaces = 0; + + ret = sysfs_add_meshif(soft_iface); + + if (ret < 0) + goto unreg_soft_iface; + + ret = debugfs_add_meshif(soft_iface); + + if (ret < 0) + goto unreg_sysfs; + + return soft_iface; + +unreg_sysfs: + sysfs_del_meshif(soft_iface); +unreg_soft_iface: + unregister_netdev(soft_iface); + return NULL; + +free_soft_iface: + free_netdev(soft_iface); +out: + return NULL; +} + +void softif_destroy(struct net_device *soft_iface) +{ + debugfs_del_meshif(soft_iface); + sysfs_del_meshif(soft_iface); + unregister_netdevice(soft_iface); +} + /* ethtool */ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h index 9dbf5fc..04f04b4 100644 --- a/drivers/staging/batman-adv/soft-interface.h +++ b/drivers/staging/batman-adv/soft-interface.h @@ -23,10 +23,12 @@ #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
void set_main_if_addr(uint8_t *addr); -void interface_setup(struct net_device *dev); -int interface_tx(struct sk_buff *skb, struct net_device *dev); -void interface_rx(struct sk_buff *skb, int hdr_size); int my_skb_head_push(struct sk_buff *skb, unsigned int len); +int interface_tx(struct sk_buff *skb, struct net_device *soft_iface); +void interface_rx(struct net_device *soft_iface, + struct sk_buff *skb, int hdr_size); +struct net_device *softif_create(char *name); +void softif_destroy(struct net_device *soft_iface);
extern unsigned char main_if_addr[];
diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index b233377..55e5e08 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -34,7 +34,8 @@ static DEFINE_SPINLOCK(hna_global_hash_lock);
static void hna_local_purge(struct work_struct *work); static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge); -static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, +static void _hna_global_del_orig(struct bat_priv *bat_priv, + struct hna_global_entry *hna_global_entry, char *message);
static void hna_local_start_timer(void) @@ -58,10 +59,9 @@ int hna_local_init(void) return 1; }
-void hna_local_add(uint8_t *addr) +void hna_local_add(struct net_device *soft_iface, uint8_t *addr) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + struct bat_priv *bat_priv = netdev_priv(soft_iface); struct hna_local_entry *hna_local_entry; struct hna_global_entry *hna_global_entry; struct hashtable_t *swaphash; @@ -100,7 +100,7 @@ void hna_local_add(uint8_t *addr) hna_local_entry->last_seen = jiffies;
/* the batman interface mac address should never be purged */ - if (compare_orig(addr, soft_device->dev_addr)) + if (compare_orig(addr, soft_iface->dev_addr)) hna_local_entry->never_purge = 1; else hna_local_entry->never_purge = 0; @@ -130,7 +130,8 @@ void hna_local_add(uint8_t *addr) ((struct hna_global_entry *)hash_find(hna_global_hash, addr));
if (hna_global_entry != NULL) - _hna_global_del_orig(hna_global_entry, "local hna received"); + _hna_global_del_orig(bat_priv, hna_global_entry, + "local hna received");
spin_unlock_irqrestore(&hna_global_hash_lock, flags); } @@ -214,26 +215,26 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) return 0; }
-static void _hna_local_del(void *data) +static void _hna_local_del(void *data, void *arg) { kfree(data); num_hna--; atomic_set(&hna_local_changed, 1); }
-static void hna_local_del(struct hna_local_entry *hna_local_entry, +static void hna_local_del(struct bat_priv *bat_priv, + struct hna_local_entry *hna_local_entry, char *message) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", hna_local_entry->addr, message);
hash_remove(hna_local_hash, hna_local_entry->addr); - _hna_local_del(hna_local_entry); + _hna_local_del(hna_local_entry, bat_priv); }
-void hna_local_remove(uint8_t *addr, char *message) +void hna_local_remove(struct bat_priv *bat_priv, + uint8_t *addr, char *message) { struct hna_local_entry *hna_local_entry; unsigned long flags; @@ -243,7 +244,7 @@ void hna_local_remove(uint8_t *addr, char *message) hna_local_entry = (struct hna_local_entry *) hash_find(hna_local_hash, addr); if (hna_local_entry) - hna_local_del(hna_local_entry, message); + hna_local_del(bat_priv, hna_local_entry, message);
spin_unlock_irqrestore(&hna_local_hash_lock, flags); } @@ -261,9 +262,10 @@ static void hna_local_purge(struct work_struct *work) hna_local_entry = hashit.bucket->data;
timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ; - if ((!hna_local_entry->never_purge) && + /* if ((!hna_local_entry->never_purge) && time_after(jiffies, timeout)) - hna_local_del(hna_local_entry, "address timed out"); + hna_local_del(bat_priv, hna_local_entry, + "address timed out");*/ }
spin_unlock_irqrestore(&hna_local_hash_lock, flags); @@ -276,7 +278,7 @@ void hna_local_free(void) return;
cancel_delayed_work_sync(&hna_local_purge_wq); - hash_delete(hna_local_hash, _hna_local_del); + hash_delete(hna_local_hash, _hna_local_del, NULL); hna_local_hash = NULL; }
@@ -293,11 +295,10 @@ int hna_global_init(void) return 1; }
-void hna_global_add_orig(struct orig_node *orig_node, +void hna_global_add_orig(struct bat_priv *bat_priv, + struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); struct hna_global_entry *hna_global_entry; struct hna_local_entry *hna_local_entry; struct hashtable_t *swaphash; @@ -345,7 +346,8 @@ void hna_global_add_orig(struct orig_node *orig_node, hash_find(hna_local_hash, hna_ptr);
if (hna_local_entry != NULL) - hna_local_del(hna_local_entry, "global hna received"); + hna_local_del(bat_priv, hna_local_entry, + "global hna received");
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
@@ -429,11 +431,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) return 0; }
-static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, +static void _hna_global_del_orig(struct bat_priv *bat_priv, + struct hna_global_entry *hna_global_entry, char *message) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); bat_dbg(DBG_ROUTES, bat_priv, "Deleting global hna entry %pM (via %pM): %s\n", hna_global_entry->addr, hna_global_entry->orig_node->orig, @@ -443,7 +444,8 @@ static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, kfree(hna_global_entry); }
-void hna_global_del_orig(struct orig_node *orig_node, char *message) +void hna_global_del_orig(struct bat_priv *bat_priv, + struct orig_node *orig_node, char *message) { struct hna_global_entry *hna_global_entry; int hna_buff_count = 0; @@ -462,7 +464,8 @@ void hna_global_del_orig(struct orig_node *orig_node, char *message)
if ((hna_global_entry != NULL) && (hna_global_entry->orig_node == orig_node)) - _hna_global_del_orig(hna_global_entry, message); + _hna_global_del_orig(bat_priv, hna_global_entry, + message);
hna_buff_count++; } @@ -474,7 +477,7 @@ void hna_global_del_orig(struct orig_node *orig_node, char *message) orig_node->hna_buff = NULL; }
-static void hna_global_del(void *data) +static void hna_global_del(void *data, void *arg) { kfree(data); } @@ -484,7 +487,7 @@ void hna_global_free(void) if (!hna_global_hash) return;
- hash_delete(hna_global_hash, hna_global_del); + hash_delete(hna_global_hash, hna_global_del, NULL); hna_global_hash = NULL; }
diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h index fa93e37..af7a59c 100644 --- a/drivers/staging/batman-adv/translation-table.h +++ b/drivers/staging/batman-adv/translation-table.h @@ -25,16 +25,19 @@ #include "types.h"
int hna_local_init(void); -void hna_local_add(uint8_t *addr); -void hna_local_remove(uint8_t *addr, char *message); +void hna_local_add(struct net_device *soft_iface, uint8_t *addr); +void hna_local_remove(struct bat_priv *bat_priv, + uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); int hna_local_seq_print_text(struct seq_file *seq, void *offset); void hna_local_free(void); int hna_global_init(void); -void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, - int hna_buff_len); +void hna_global_add_orig(struct bat_priv *bat_priv, + struct orig_node *orig_node, + unsigned char *hna_buff, int hna_buff_len); int hna_global_seq_print_text(struct seq_file *seq, void *offset); -void hna_global_del_orig(struct orig_node *orig_node, char *message); +void hna_global_del_orig(struct bat_priv *bat_priv, + struct orig_node *orig_node, char *message); void hna_global_free(void); struct orig_node *transtable_search(uint8_t *addr);
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 4b2e832..c5b738d 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -47,6 +47,7 @@ struct batman_if { struct kobject *hardif_obj; struct rcu_head rcu; struct packet_type batman_adv_ptype; + struct net_device *soft_iface; };
/** diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index e89a710..ad899fe 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -745,17 +745,16 @@ static void send_vis_packets(struct work_struct *work) { struct vis_info *info, *temp; unsigned long flags; - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); + /* struct bat_priv *bat_priv = netdev_priv(soft_device); */
spin_lock_irqsave(&vis_hash_lock, flags);
purge_vis_packets();
- if (generate_vis_packet(bat_priv) == 0) { + /* if (generate_vis_packet(bat_priv) == 0) {*/ /* schedule if generation was successful */ - send_list_add(my_vis_info); - } + /*send_list_add(my_vis_info); + } */
list_for_each_entry_safe(info, temp, &send_list, send_list) {
@@ -842,7 +841,7 @@ err: }
/* Decrease the reference count on a hash item info */ -static void free_info_ref(void *data) +static void free_info_ref(void *data, void *arg) { struct vis_info *info = data;
@@ -861,7 +860,7 @@ void vis_quit(void)
spin_lock_irqsave(&vis_hash_lock, flags); /* properly remove, kill timers ... */ - hash_delete(vis_hash, free_info_ref); + hash_delete(vis_hash, free_info_ref, NULL); vis_hash = NULL; my_vis_info = NULL; spin_unlock_irqrestore(&vis_hash_lock, flags);
From: Marek Lindner lindner_marek@yahoo.de
This patch removes all remaining global variables and includes the necessary bits into the bat_priv structure. It is the last remaining piece to allow multiple concurrent mesh clouds on the same device. A few global variables have been rendered obsolete during the process and have been removed entirely.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de [sven.eckelmann@gmx.de: Rework on top of current version] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/aggregation.c | 22 +- drivers/staging/batman-adv/bat_sysfs.c | 2 +- drivers/staging/batman-adv/hard-interface.c | 48 ++-- drivers/staging/batman-adv/icmp_socket.c | 11 +- drivers/staging/batman-adv/main.c | 74 +++--- drivers/staging/batman-adv/main.h | 22 +-- drivers/staging/batman-adv/originator.c | 119 +++++---- drivers/staging/batman-adv/originator.h | 6 +- drivers/staging/batman-adv/routing.c | 115 +++++---- drivers/staging/batman-adv/routing.h | 3 +- drivers/staging/batman-adv/send.c | 110 +++++---- drivers/staging/batman-adv/send.h | 3 +- drivers/staging/batman-adv/soft-interface.c | 48 ++-- drivers/staging/batman-adv/soft-interface.h | 3 - drivers/staging/batman-adv/translation-table.c | 219 ++++++++-------- drivers/staging/batman-adv/translation-table.h | 17 +- drivers/staging/batman-adv/types.h | 81 +++++-- drivers/staging/batman-adv/unicast.c | 17 +- drivers/staging/batman-adv/vis.c | 333 +++++++++++++----------- drivers/staging/batman-adv/vis.h | 27 +-- 20 files changed, 680 insertions(+), 600 deletions(-)
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c index 6e10fe5..46b9c2b 100644 --- a/drivers/staging/batman-adv/aggregation.c +++ b/drivers/staging/batman-adv/aggregation.c @@ -102,10 +102,10 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, struct batman_if *if_incoming, int own_packet) { - struct forw_packet *forw_packet_aggr; - unsigned long flags; - unsigned char *skb_buff; struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct forw_packet *forw_packet_aggr; + unsigned long flags; + unsigned char *skb_buff;
/* own packet should always be scheduled */ if (!own_packet) { @@ -150,9 +150,9 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, forw_packet_aggr->direct_link_flags |= 1;
/* add new packet to packet list */ - spin_lock_irqsave(&forw_bat_list_lock, flags); - hlist_add_head(&forw_packet_aggr->list, &forw_bat_list); - spin_unlock_irqrestore(&forw_bat_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags); + hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list); + spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
/* start timer for this packet */ INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, @@ -198,11 +198,11 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, unsigned long flags;
/* find position for the packet in the forward queue */ - spin_lock_irqsave(&forw_bat_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags); /* own packets are not to be aggregated */ if ((atomic_read(&bat_priv->aggregation_enabled)) && (!own_packet)) { - hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list, - list) { + hlist_for_each_entry(forw_packet_pos, tmp_node, + &bat_priv->forw_bat_list, list) { if (can_aggregate_with(batman_packet, packet_len, send_time, @@ -219,7 +219,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, * suitable aggregation packet found */ if (forw_packet_aggr == NULL) { /* the following section can run without the lock */ - spin_unlock_irqrestore(&forw_bat_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
/** * if we could not aggregate this packet with one of the others @@ -237,7 +237,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, aggregate(forw_packet_aggr, packet_buff, packet_len, direct_link); - spin_unlock_irqrestore(&forw_bat_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags); } }
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index 052f9e8..0610169 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -411,7 +411,7 @@ static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
return sprintf(buff, "%s\n", batman_if->if_status == IF_NOT_IN_USE ? - "none" : "bat0"); + "none" : batman_if->soft_iface->name); }
static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index d31cfc3..6b8ec28 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -77,13 +77,15 @@ static int is_valid_iface(struct net_device *net_dev) return 1; }
-static struct batman_if *get_active_batman_if(void) +static struct batman_if *get_active_batman_if(struct net_device *soft_iface) { struct batman_if *batman_if;
- /* TODO: should check interfaces belonging to bat_priv */ rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->soft_iface != soft_iface) + continue; + if (batman_if->if_status == IF_ACTIVE) goto out; } @@ -99,23 +101,29 @@ static void set_primary_if(struct bat_priv *bat_priv, struct batman_if *batman_if) { struct batman_packet *batman_packet; + struct vis_packet *vis_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;
+ vis_packet = (struct vis_packet *) + bat_priv->my_vis_info->skb_packet->data; + memcpy(vis_packet->vis_orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(vis_packet->sender_orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + /*** * hacky trick to make sure that we send the HNA information via * our new primary interface */ - atomic_set(&hna_local_changed, 1); + atomic_set(&bat_priv->hna_local_changed, 1); }
static bool hardif_is_iface_up(struct batman_if *batman_if) @@ -217,9 +225,6 @@ static void hardif_activate_interface(struct batman_if *batman_if) bat_info(batman_if->soft_iface, "Interface activated: %s\n", batman_if->dev);
- if (atomic_read(&module_state) == MODULE_INACTIVE) - activate_module(); - update_min_mtu(batman_if->soft_iface); return; } @@ -347,11 +352,16 @@ void hardif_disable_interface(struct batman_if *batman_if) orig_hash_del_if(batman_if, bat_priv->num_ifaces);
if (batman_if == bat_priv->primary_if) - set_primary_if(bat_priv, get_active_batman_if()); + set_primary_if(bat_priv, + get_active_batman_if(batman_if->soft_iface));
kfree(batman_if->packet_buff); batman_if->packet_buff = NULL; batman_if->if_status = IF_NOT_IN_USE; + + /* delete all references to this batman_if */ + purge_orig_ref(bat_priv); + purge_outstanding_packets(bat_priv, batman_if); dev_put(batman_if->soft_iface);
/* nobody uses this interface anymore */ @@ -359,10 +369,6 @@ void hardif_disable_interface(struct batman_if *batman_if) softif_destroy(batman_if->soft_iface);
batman_if->soft_iface = NULL; - - /*if ((atomic_read(&module_state) == MODULE_ACTIVE) && - (bat_priv->num_ifaces == 0)) - deactivate_module();*/ }
static struct batman_if *hardif_add_interface(struct net_device *net_dev) @@ -415,10 +421,6 @@ static void hardif_free_interface(struct rcu_head *rcu) { struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu);
- /* delete all references to this batman_if */ - purge_orig(NULL); - purge_outstanding_packets(batman_if); - kfree(batman_if->dev); kfree(batman_if); } @@ -512,9 +514,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (!skb) goto err_out;
- if (atomic_read(&module_state) != MODULE_ACTIVE) - goto err_free; - /* packet should hold at least type and version */ if (unlikely(!pskb_may_pull(skb, 2))) goto err_free; @@ -524,12 +523,19 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, || !skb_mac_header(skb))) goto err_free;
+ if (!batman_if->soft_iface) + goto err_free; + + bat_priv = netdev_priv(batman_if->soft_iface); + + if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) + goto err_free; + /* discard frames on not active interfaces */ if (batman_if->if_status != IF_ACTIVE) goto err_free;
batman_packet = (struct batman_packet *)skb->data; - bat_priv = netdev_priv(batman_if->soft_iface);
if (batman_packet->version != COMPAT_VERSION) { bat_dbg(DBG_BATMAN, bat_priv, diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index 2a1d3dd..24627be 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -218,11 +218,12 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, goto free_skb; }
- if (atomic_read(&module_state) != MODULE_ACTIVE) + if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dst_unreach;
- spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = (struct orig_node *)hash_find(orig_hash, icmp_packet->dst); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, + icmp_packet->dst));
if (!orig_node) goto unlock; @@ -233,7 +234,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
if (!batman_if) goto dst_unreach; @@ -253,7 +254,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, goto out;
unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); dst_unreach: icmp_packet->msg_type = DESTINATION_UNREACHABLE; bat_socket_add_packet(socket_client, icmp_packet, packet_len); diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 52c019b..498861f 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -34,28 +34,14 @@ #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); - -int16_t num_hna;
unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -atomic_t module_state;
struct workqueue_struct *bat_event_workqueue;
static int __init batman_init(void) { INIT_LIST_HEAD(&if_list); - INIT_HLIST_HEAD(&forw_bat_list); - INIT_HLIST_HEAD(&forw_bcast_list); - - atomic_set(&module_state, MODULE_INACTIVE);
/* the name should not be longer than 10 chars - see * http://lwn.net/Articles/23634/ */ @@ -78,64 +64,78 @@ static int __init batman_init(void)
static void __exit batman_exit(void) { - deactivate_module(); - debugfs_destroy(); unregister_netdevice_notifier(&hard_if_notifier); hardif_remove_interfaces();
+ flush_workqueue(bat_event_workqueue); destroy_workqueue(bat_event_workqueue); bat_event_workqueue = NULL; }
-/* activates the module, starts timer ... */ -void activate_module(void) +int mesh_init(struct net_device *soft_iface) { - if (originator_init() < 1) + struct bat_priv *bat_priv = netdev_priv(soft_iface); + + spin_lock_init(&bat_priv->orig_hash_lock); + spin_lock_init(&bat_priv->forw_bat_list_lock); + spin_lock_init(&bat_priv->forw_bcast_list_lock); + spin_lock_init(&bat_priv->hna_lhash_lock); + spin_lock_init(&bat_priv->hna_ghash_lock); + spin_lock_init(&bat_priv->gw_list_lock); + spin_lock_init(&bat_priv->vis_hash_lock); + spin_lock_init(&bat_priv->vis_list_lock); + + INIT_HLIST_HEAD(&bat_priv->forw_bat_list); + INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); + INIT_HLIST_HEAD(&bat_priv->gw_list); + + if (originator_init(bat_priv) < 1) goto err;
- if (hna_local_init() < 1) + if (hna_local_init(bat_priv) < 1) goto err;
- if (hna_global_init() < 1) + if (hna_global_init(bat_priv) < 1) goto err;
- /*hna_local_add(soft_device->dev_addr);*/ + hna_local_add(soft_iface, soft_iface->dev_addr);
- if (vis_init() < 1) + if (vis_init(bat_priv) < 1) goto err;
- /*update_min_mtu();*/ - atomic_set(&module_state, MODULE_ACTIVE); + atomic_set(&bat_priv->mesh_state, MESH_ACTIVE); goto end;
err: pr_err("Unable to allocate memory for mesh information structures: " "out of mem ?\n"); - deactivate_module(); + mesh_free(soft_iface); + return -1; + end: - return; + return 0; }
-/* shuts down the whole module.*/ -void deactivate_module(void) +void mesh_free(struct net_device *soft_iface) { - atomic_set(&module_state, MODULE_DEACTIVATING); + struct bat_priv *bat_priv = netdev_priv(soft_iface);
- purge_outstanding_packets(NULL); - flush_workqueue(bat_event_workqueue); + atomic_set(&bat_priv->mesh_state, MESH_DEACTIVATING);
- vis_quit(); + purge_outstanding_packets(bat_priv, NULL);
- originator_free(); + vis_quit(bat_priv);
- hna_local_free(); - hna_global_free(); + originator_free(bat_priv); + + hna_local_free(bat_priv); + hna_global_free(bat_priv);
synchronize_net();
synchronize_rcu(); - atomic_set(&module_state, MODULE_INACTIVE); + atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); }
void inc_module_count(void) diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index 2309d82..ca97589 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -76,9 +76,9 @@ #define EXPECTED_SEQNO_RANGE 65536 /* don't reset again within 30 seconds */
-#define MODULE_INACTIVE 0 -#define MODULE_ACTIVE 1 -#define MODULE_DEACTIVATING 2 +#define MESH_INACTIVE 0 +#define MESH_ACTIVE 1 +#define MESH_DEACTIVATING 2
#define BCAST_QUEUE_LEN 256 #define BATMAN_QUEUE_LEN 256 @@ -128,22 +128,12 @@ #endif
extern struct list_head if_list; -extern struct hlist_head forw_bat_list; -extern struct hlist_head forw_bcast_list; -extern struct hashtable_t *orig_hash; - -extern spinlock_t orig_hash_lock; -extern spinlock_t forw_bat_list_lock; -extern spinlock_t forw_bcast_list_lock; - -extern int16_t num_hna;
extern unsigned char broadcast_addr[]; -extern atomic_t module_state; extern struct workqueue_struct *bat_event_workqueue;
-void activate_module(void); -void deactivate_module(void); +int mesh_init(struct net_device *soft_iface); +void mesh_free(struct net_device *soft_iface); void inc_module_count(void); void dec_module_count(void); int addr_to_string(char *buff, uint8_t *addr); @@ -154,7 +144,7 @@ int is_bcast(uint8_t *addr); int is_mcast(uint8_t *addr);
#ifdef CONFIG_BATMAN_ADV_DEBUG -extern int debug_log(struct bat_priv *bat_priv, char *fmt, ...); +int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
#define bat_dbg(type, bat_priv, fmt, arg...) \ do { \ diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 7ed3266..d20721b 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -29,31 +29,32 @@ #include "hard-interface.h" #include "unicast.h"
-static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); +static void purge_orig(struct work_struct *work);
-static void start_purge_timer(void) +static void start_purge_timer(struct bat_priv *bat_priv) { - queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ); + INIT_DELAYED_WORK(&bat_priv->orig_work, purge_orig); + queue_delayed_work(bat_event_workqueue, &bat_priv->orig_work, 1 * HZ); }
-int originator_init(void) +int originator_init(struct bat_priv *bat_priv) { unsigned long flags; - if (orig_hash) + if (bat_priv->orig_hash) return 1;
- spin_lock_irqsave(&orig_hash_lock, flags); - orig_hash = hash_new(128, compare_orig, choose_orig); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + bat_priv->orig_hash = hash_new(128, compare_orig, choose_orig);
- if (!orig_hash) + if (!bat_priv->orig_hash) goto err;
- spin_unlock_irqrestore(&orig_hash_lock, flags); - start_purge_timer(); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + start_purge_timer(bat_priv); return 1;
err: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return 0; }
@@ -104,19 +105,19 @@ static void free_orig_node(void *data, void *arg) kfree(orig_node); }
-void originator_free(void) +void originator_free(struct bat_priv *bat_priv) { unsigned long flags;
- if (!orig_hash) + if (!bat_priv->orig_hash) return;
- cancel_delayed_work_sync(&purge_orig_wq); + cancel_delayed_work_sync(&bat_priv->orig_work);
- spin_lock_irqsave(&orig_hash_lock, flags); - /*hash_delete(orig_hash, free_orig_node, bat_priv);*/ - orig_hash = NULL; - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + hash_delete(bat_priv->orig_hash, free_orig_node, bat_priv); + bat_priv->orig_hash = NULL; + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); }
/* this function finds or creates an originator entry for the given @@ -127,9 +128,9 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) struct hashtable_t *swaphash; int size;
- orig_node = ((struct orig_node *)hash_find(orig_hash, addr)); + orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, addr));
- if (orig_node != NULL) + if (orig_node) return orig_node;
bat_dbg(DBG_BATMAN, bat_priv, @@ -164,17 +165,18 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) if (!orig_node->bcast_own_sum) goto free_bcast_own;
- if (hash_add(orig_hash, orig_node) < 0) + if (hash_add(bat_priv->orig_hash, orig_node) < 0) goto free_bcast_own_sum;
- if (orig_hash->elements * 4 > orig_hash->size) { - swaphash = hash_resize(orig_hash, orig_hash->size * 2); + if (bat_priv->orig_hash->elements * 4 > bat_priv->orig_hash->size) { + swaphash = hash_resize(bat_priv->orig_hash, + bat_priv->orig_hash->size * 2);
- if (swaphash == NULL) + if (!swaphash) bat_dbg(DBG_BATMAN, bat_priv, "Couldn't resize orig hash table\n"); else - orig_hash = swaphash; + bat_priv->orig_hash = swaphash; }
return orig_node; @@ -203,8 +205,8 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
if ((time_after(jiffies, neigh_node->last_valid + PURGE_TIMEOUT * HZ)) || - (neigh_node->if_incoming->if_status == - IF_TO_BE_REMOVED)) { + (neigh_node->if_incoming->if_status == IF_INACTIVE) || + (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
if (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED) @@ -260,34 +262,46 @@ static bool purge_orig_node(struct bat_priv *bat_priv, return false; }
-void purge_orig(struct work_struct *work) +static void _purge_orig(struct bat_priv *bat_priv) { HASHIT(hashit); struct orig_node *orig_node; unsigned long flags;
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
/* for all origins... */ - while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) { orig_node = hashit.bucket->data;
- /*if (purge_orig_node(bat_priv, orig_node)) { - hash_remove_bucket(orig_hash, &hashit); - free_orig_node(orig_node); - }*/ + if (purge_orig_node(bat_priv, orig_node)) { + hash_remove_bucket(bat_priv->orig_hash, &hashit); + free_orig_node(orig_node, bat_priv); + }
if (time_after(jiffies, (orig_node->last_frag_packet + msecs_to_jiffies(FRAG_TIMEOUT)))) frag_list_free(&orig_node->frag_list); }
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
- /* 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(); +} + +static void purge_orig(struct work_struct *work) +{ + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct bat_priv *bat_priv = + container_of(delayed_work, struct bat_priv, orig_work); + + _purge_orig(bat_priv); + start_purge_timer(bat_priv); +} + +void purge_orig_ref(struct bat_priv *bat_priv) +{ + _purge_orig(bat_priv); }
int orig_seq_print_text(struct seq_file *seq, void *offset) @@ -325,9 +339,9 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) "outgoingIF", "Potential nexthops"); rcu_read_unlock();
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
@@ -359,7 +373,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) batman_count++; }
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
if ((batman_count == 0)) seq_printf(seq, "No batman nodes in range ...\n"); @@ -399,26 +413,27 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) { + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct orig_node *orig_node; unsigned long flags; HASHIT(hashit);
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) { orig_node = hashit.bucket->data;
if (orig_node_add_if(orig_node, max_if_num) == -1) goto err; }
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return 0;
err: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return -ENOMEM; }
@@ -476,6 +491,7 @@ free_own_sum:
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) { + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct batman_if *batman_if_tmp; struct orig_node *orig_node; unsigned long flags; @@ -484,9 +500,9 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) { orig_node = hashit.bucket->data;
ret = orig_node_del_if(orig_node, max_if_num, @@ -505,16 +521,19 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) if (batman_if == batman_if_tmp) continue;
+ if (batman_if->soft_iface != batman_if_tmp->soft_iface) + 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_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return 0;
err: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return -ENOMEM; } diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h index bc47c68..a97c400 100644 --- a/drivers/staging/batman-adv/originator.h +++ b/drivers/staging/batman-adv/originator.h @@ -22,9 +22,9 @@ #ifndef _NET_BATMAN_ADV_ORIGINATOR_H_ #define _NET_BATMAN_ADV_ORIGINATOR_H_
-int originator_init(void); -void originator_free(void); -void purge_orig(struct work_struct *work); +int originator_init(struct bat_priv *bat_priv); +void originator_free(struct bat_priv *bat_priv); +void purge_orig_ref(struct bat_priv *bat_priv); struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); struct neigh_node * create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 3cae7c4..34cc321 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -34,8 +34,6 @@ #include "aggregation.h" #include "unicast.h"
-static DECLARE_WAIT_QUEUE_HEAD(thread_wait); - void slide_own_bcast_window(struct batman_if *batman_if) { struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); @@ -44,9 +42,9 @@ void slide_own_bcast_window(struct batman_if *batman_if) TYPE_OF_WORD *word; unsigned long flags;
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) { orig_node = hashit.bucket->data; word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
@@ -55,7 +53,7 @@ void slide_own_bcast_window(struct batman_if *batman_if) bit_packet_count(word); }
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); }
static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, @@ -568,6 +566,9 @@ void receive_bat_packet(struct ethhdr *ethhdr, if (batman_if->if_status != IF_ACTIVE) continue;
+ if (batman_if->soft_iface != if_incoming->soft_iface) + continue; + if (compare_orig(ethhdr->h_source, batman_if->net_dev->dev_addr)) is_my_addr = 1; @@ -739,9 +740,9 @@ void receive_bat_packet(struct ethhdr *ethhdr, 0, hna_buff_len, if_incoming); }
-int recv_bat_packet(struct sk_buff *skb, - struct batman_if *batman_if) +int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) { + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct ethhdr *ethhdr; unsigned long flags;
@@ -769,22 +770,20 @@ int recv_bat_packet(struct sk_buff *skb,
ethhdr = (struct ethhdr *)skb_mac_header(skb);
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); receive_aggr_bat_packet(ethhdr, skb->data, skb_headlen(skb), batman_if); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
kfree_skb(skb); return NET_RX_SUCCESS; }
-static int recv_my_icmp_packet(struct sk_buff *skb, - struct batman_if *recv_if, size_t icmp_len) +static int recv_my_icmp_packet(struct bat_priv *bat_priv, + struct sk_buff *skb, size_t icmp_len) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; @@ -807,8 +806,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb,
/* answer echo request (ping) */ /* get routing information */ - spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, icmp_packet->orig)); ret = NET_RX_DROP;
@@ -819,7 +818,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb, * copy the required data before sending */ batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -838,16 +837,14 @@ static int recv_my_icmp_packet(struct sk_buff *skb, ret = NET_RX_SUCCESS;
} else - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
return ret; }
-static int recv_icmp_ttl_exceeded(struct sk_buff *skb, - struct batman_if *recv_if, size_t icmp_len) +static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, + struct sk_buff *skb, size_t icmp_len) { - /* FIXME: each batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; struct icmp_packet *icmp_packet; struct ethhdr *ethhdr; @@ -871,9 +868,9 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, return NET_RX_DROP;
/* get routing information */ - spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); orig_node = ((struct orig_node *) - hash_find(orig_hash, icmp_packet->orig)); + hash_find(bat_priv->orig_hash, icmp_packet->orig)); ret = NET_RX_DROP;
if ((orig_node != NULL) && @@ -883,7 +880,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, * copy the required data before sending */ batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -902,7 +899,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, ret = NET_RX_SUCCESS;
} else - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
return ret; } @@ -910,6 +907,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb,
int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if) { + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; struct orig_node *orig_node; @@ -955,18 +953,18 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
/* packet for me */ if (is_my_mac(icmp_packet->dst)) - return recv_my_icmp_packet(skb, recv_if, hdr_size); + return recv_my_icmp_packet(bat_priv, skb, hdr_size);
/* TTL exceeded */ if (icmp_packet->ttl < 2) - return recv_icmp_ttl_exceeded(skb, recv_if, hdr_size); + return recv_icmp_ttl_exceeded(bat_priv, skb, hdr_size);
ret = NET_RX_DROP;
/* get routing information */ - spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); orig_node = ((struct orig_node *) - hash_find(orig_hash, icmp_packet->dst)); + hash_find(bat_priv->orig_hash, icmp_packet->dst));
if ((orig_node != NULL) && (orig_node->router != NULL)) { @@ -975,7 +973,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if) * copy the required data before sending */ batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -992,7 +990,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if) ret = NET_RX_SUCCESS;
} else - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
return ret; } @@ -1041,8 +1039,9 @@ struct neigh_node *find_router(struct orig_node *orig_node, router_orig->orig, ETH_ALEN) == 0) { primary_orig_node = router_orig; } else { - primary_orig_node = hash_find(orig_hash, + primary_orig_node = hash_find(bat_priv->orig_hash, router_orig->primary_addr); + if (!primary_orig_node) return orig_node->router; } @@ -1122,6 +1121,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, int hdr_size) { + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; struct neigh_node *router; struct batman_if *batman_if; @@ -1147,14 +1147,14 @@ static int route_unicast_packet(struct sk_buff *skb, }
/* get routing information */ - spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); orig_node = ((struct orig_node *) - hash_find(orig_hash, unicast_packet->dest)); + hash_find(bat_priv->orig_hash, unicast_packet->dest));
router = find_router(orig_node, recv_if);
if (!router) { - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return NET_RX_DROP; }
@@ -1164,13 +1164,13 @@ static int route_unicast_packet(struct sk_buff *skb, batman_if = router->if_incoming; memcpy(dstaddr, router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) return NET_RX_DROP;
- unicast_packet = (struct unicast_packet *) skb->data; + unicast_packet = (struct unicast_packet *)skb->data; ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* decrement ttl */ @@ -1203,6 +1203,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) { + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct unicast_frag_packet *unicast_packet; struct orig_node *orig_node; struct frag_packet_list_entry *tmp_frag_entry; @@ -1212,19 +1213,20 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) if (check_unicast_packet(skb, hdr_size) < 0) return NET_RX_DROP;
- unicast_packet = (struct unicast_frag_packet *) skb->data; + unicast_packet = (struct unicast_frag_packet *)skb->data;
/* packet for me */ if (is_my_mac(unicast_packet->dest)) {
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); orig_node = ((struct orig_node *) - hash_find(orig_hash, unicast_packet->orig)); + hash_find(bat_priv->orig_hash, unicast_packet->orig));
if (!orig_node) { pr_warning("couldn't find orig node for " "fragmentation\n"); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, + flags); return NET_RX_DROP; }
@@ -1235,17 +1237,18 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
tmp_frag_entry = search_frag_packet(&orig_node->frag_list, - unicast_packet); + unicast_packet);
if (!tmp_frag_entry) { create_frag_entry(&orig_node->frag_list, skb); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, + flags); return NET_RX_SUCCESS; }
skb = merge_frag_packet(&orig_node->frag_list, - tmp_frag_entry, skb); - spin_unlock_irqrestore(&orig_hash_lock, flags); + tmp_frag_entry, skb); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); if (!skb) return NET_RX_DROP;
@@ -1257,12 +1260,12 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) }
-int recv_bcast_packet(struct sk_buff *skb, struct batman_if *batman_if) +int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if) { + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; struct bcast_packet *bcast_packet; struct ethhdr *ethhdr; - struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); int hdr_size = sizeof(struct bcast_packet); int32_t seq_diff; unsigned long flags; @@ -1294,12 +1297,12 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *batman_if) if (bcast_packet->ttl < 2) return NET_RX_DROP;
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); orig_node = ((struct orig_node *) - hash_find(orig_hash, bcast_packet->orig)); + hash_find(bat_priv->orig_hash, bcast_packet->orig));
if (orig_node == NULL) { - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return NET_RX_DROP; }
@@ -1307,7 +1310,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *batman_if) if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohl(bcast_packet->seqno))) { - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return NET_RX_DROP; }
@@ -1316,7 +1319,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *batman_if) /* check whether the packet is old and the host just restarted. */ if (window_protected(bat_priv, seq_diff, &orig_node->bcast_seqno_reset)) { - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return NET_RX_DROP; }
@@ -1325,21 +1328,21 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *batman_if) if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1)) orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); /* rebroadcast packet */ add_bcast_packet_to_list(bat_priv, skb);
/* broadcast for me */ - interface_rx(batman_if->soft_iface, skb, hdr_size); + interface_rx(recv_if->soft_iface, skb, hdr_size);
return NET_RX_SUCCESS; }
-int recv_vis_packet(struct sk_buff *skb, struct batman_if *batman_if) +int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if) { struct vis_packet *vis_packet; struct ethhdr *ethhdr; - struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); + struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); int hdr_size = sizeof(struct vis_packet);
/* keep skb linear */ diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 55995e4..06ea99d 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -37,8 +37,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if); -int recv_bat_packet(struct sk_buff *skb, - struct batman_if *batman_if); +int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if); struct neigh_node *find_router(struct orig_node *orig_node, struct batman_if *recv_if); void update_bonding_candidates(struct bat_priv *bat_priv, diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 3505d1b..e9980ef 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -160,8 +160,8 @@ static void send_packet_to_if(struct forw_packet *forw_packet, static void send_packet(struct forw_packet *forw_packet) { struct batman_if *batman_if; - struct bat_priv *bat_priv = - netdev_priv(forw_packet->if_incoming->soft_iface); + struct net_device *soft_iface = forw_packet->if_incoming->soft_iface; + struct bat_priv *bat_priv = netdev_priv(soft_iface); struct batman_packet *batman_packet = (struct batman_packet *)(forw_packet->skb->data); unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0); @@ -199,18 +199,24 @@ static void send_packet(struct forw_packet *forw_packet)
/* broadcast on every interface */ rcu_read_lock(); - list_for_each_entry_rcu(batman_if, &if_list, list) + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->soft_iface != soft_iface) + continue; + send_packet_to_if(forw_packet, batman_if); + } rcu_read_unlock(); }
-static void rebuild_batman_packet(struct batman_if *batman_if) +static void rebuild_batman_packet(struct bat_priv *bat_priv, + struct batman_if *batman_if) { int new_len; unsigned char *new_buff; struct batman_packet *batman_packet;
- new_len = sizeof(struct batman_packet) + (num_hna * ETH_ALEN); + new_len = sizeof(struct batman_packet) + + (bat_priv->num_local_hna * ETH_ALEN); new_buff = kmalloc(new_len, GFP_ATOMIC);
/* keep old buffer if kmalloc should fail */ @@ -219,9 +225,9 @@ static void rebuild_batman_packet(struct batman_if *batman_if) sizeof(struct batman_packet)); batman_packet = (struct batman_packet *)new_buff;
- batman_packet->num_hna = hna_local_fill_buffer( - new_buff + sizeof(struct batman_packet), - new_len - sizeof(struct batman_packet)); + batman_packet->num_hna = hna_local_fill_buffer(bat_priv, + new_buff + sizeof(struct batman_packet), + new_len - sizeof(struct batman_packet));
kfree(batman_if->packet_buff); batman_if->packet_buff = new_buff; @@ -253,9 +259,9 @@ void schedule_own_packet(struct batman_if *batman_if) batman_if->if_status = IF_ACTIVE;
/* if local hna has changed and interface is a primary interface */ - if ((atomic_read(&hna_local_changed)) && + if ((atomic_read(&bat_priv->hna_local_changed)) && (batman_if == bat_priv->primary_if)) - rebuild_batman_packet(batman_if); + rebuild_batman_packet(bat_priv, batman_if);
/** * NOTE: packet_buff might just have been re-allocated in @@ -351,16 +357,17 @@ static void forw_packet_free(struct forw_packet *forw_packet) kfree(forw_packet); }
-static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, +static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, + struct forw_packet *forw_packet, unsigned long send_time) { unsigned long flags; INIT_HLIST_NODE(&forw_packet->list);
/* add new packet to packet list */ - spin_lock_irqsave(&forw_bcast_list_lock, flags); - hlist_add_head(&forw_packet->list, &forw_bcast_list); - spin_unlock_irqrestore(&forw_bcast_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags); + hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list); + spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
/* start timer for this packet */ INIT_DELAYED_WORK(&forw_packet->delayed_work, @@ -388,6 +395,9 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) goto out; }
+ if (!bat_priv->primary_if) + goto out; + forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
if (!forw_packet) @@ -409,7 +419,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) /* how often did we send the bcast packet ? */ forw_packet->num_packets = 0;
- _add_bcast_packet_to_list(forw_packet, 1); + _add_bcast_packet_to_list(bat_priv, forw_packet, 1); return NETDEV_TX_OK;
packet_free: @@ -429,23 +439,26 @@ static void send_outstanding_bcast_packet(struct work_struct *work) container_of(delayed_work, struct forw_packet, delayed_work); unsigned long flags; struct sk_buff *skb1; - struct bat_priv *bat_priv; + struct net_device *soft_iface = forw_packet->if_incoming->soft_iface; + struct bat_priv *bat_priv = netdev_priv(soft_iface);
- spin_lock_irqsave(&forw_bcast_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags); hlist_del(&forw_packet->list); - spin_unlock_irqrestore(&forw_bcast_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
- if (atomic_read(&module_state) == MODULE_DEACTIVATING) + if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING) goto out;
/* rebroadcast packet */ rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->soft_iface != soft_iface) + continue; + /* send a copy of the saved skb */ skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); if (skb1) - send_skb_packet(skb1, - batman_if, broadcast_addr); + send_skb_packet(skb1, batman_if, broadcast_addr); } rcu_read_unlock();
@@ -453,12 +466,12 @@ static void send_outstanding_bcast_packet(struct work_struct *work)
/* if we still have some more bcasts to send */ if (forw_packet->num_packets < 3) { - _add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000)); + _add_bcast_packet_to_list(bat_priv, forw_packet, + ((5 * HZ) / 1000)); return; }
out: - bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); forw_packet_free(forw_packet); atomic_inc(&bat_priv->bcast_queue_left); } @@ -472,11 +485,12 @@ void send_outstanding_bat_packet(struct work_struct *work) unsigned long flags; struct bat_priv *bat_priv;
- spin_lock_irqsave(&forw_bat_list_lock, flags); + bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); + spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags); hlist_del(&forw_packet->list); - spin_unlock_irqrestore(&forw_bat_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
- if (atomic_read(&module_state) == MODULE_DEACTIVATING) + if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING) goto out;
send_packet(forw_packet); @@ -490,8 +504,6 @@ void send_outstanding_bat_packet(struct work_struct *work) schedule_own_packet(forw_packet->if_incoming);
out: - bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); - /* don't count own packet */ if (!forw_packet->own) atomic_inc(&bat_priv->batman_queue_left); @@ -499,29 +511,25 @@ out: forw_packet_free(forw_packet); }
-void purge_outstanding_packets(struct batman_if *batman_if) +void purge_outstanding_packets(struct bat_priv *bat_priv, + struct batman_if *batman_if) { - struct bat_priv *bat_priv; struct forw_packet *forw_packet; struct hlist_node *tmp_node, *safe_tmp_node; unsigned long flags;
- if (batman_if->soft_iface) { - bat_priv = netdev_priv(batman_if->soft_iface); - - if (batman_if) - bat_dbg(DBG_BATMAN, bat_priv, - "purge_outstanding_packets(): %s\n", - batman_if->dev); - else - bat_dbg(DBG_BATMAN, bat_priv, - "purge_outstanding_packets()\n"); - } + if (batman_if) + bat_dbg(DBG_BATMAN, bat_priv, + "purge_outstanding_packets(): %s\n", + batman_if->dev); + else + bat_dbg(DBG_BATMAN, bat_priv, + "purge_outstanding_packets()\n");
/* free bcast list */ - spin_lock_irqsave(&forw_bcast_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags); hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, - &forw_bcast_list, list) { + &bat_priv->forw_bcast_list, list) {
/** * if purge_outstanding_packets() was called with an argmument @@ -531,21 +539,21 @@ void purge_outstanding_packets(struct batman_if *batman_if) (forw_packet->if_incoming != batman_if)) continue;
- spin_unlock_irqrestore(&forw_bcast_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
/** * send_outstanding_bcast_packet() will lock the list to * delete the item from the list */ cancel_delayed_work_sync(&forw_packet->delayed_work); - spin_lock_irqsave(&forw_bcast_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags); } - spin_unlock_irqrestore(&forw_bcast_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
/* free batman packet list */ - spin_lock_irqsave(&forw_bat_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags); hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, - &forw_bat_list, list) { + &bat_priv->forw_bat_list, list) {
/** * if purge_outstanding_packets() was called with an argmument @@ -555,14 +563,14 @@ void purge_outstanding_packets(struct batman_if *batman_if) (forw_packet->if_incoming != batman_if)) continue;
- spin_unlock_irqrestore(&forw_bat_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
/** * send_outstanding_bat_packet() will lock the list to * delete the item from the list */ cancel_delayed_work_sync(&forw_packet->delayed_work); - spin_lock_irqsave(&forw_bat_list_lock, flags); + spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags); } - spin_unlock_irqrestore(&forw_bat_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags); } diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h index 39a3426..c4cefa8 100644 --- a/drivers/staging/batman-adv/send.h +++ b/drivers/staging/batman-adv/send.h @@ -35,6 +35,7 @@ void schedule_forward_packet(struct orig_node *orig_node, struct batman_if *if_outgoing); int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); void send_outstanding_bat_packet(struct work_struct *work); -void purge_outstanding_packets(struct batman_if *batman_if); +void purge_outstanding_packets(struct bat_priv *bat_priv, + struct batman_if *batman_if);
#endif /* _NET_BATMAN_ADV_SEND_H_ */ diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 864f85d..8d14343 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -35,10 +35,7 @@ #include <linux/etherdevice.h> #include "unicast.h"
-static uint32_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid - * broadcast storms */
-unsigned char main_if_addr[ETH_ALEN]; static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); static void bat_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); @@ -58,11 +55,6 @@ static const struct ethtool_ops bat_ethtool_ops = { .set_rx_csum = bat_set_rx_csum };
-void set_main_if_addr(uint8_t *addr) -{ - memcpy(main_if_addr, addr, ETH_ALEN); -} - int my_skb_head_push(struct sk_buff *skb, unsigned int len) { int result; @@ -76,7 +68,6 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len) * to write freely in that area. */ result = skb_cow_head(skb, len); - if (result < 0) return result;
@@ -111,7 +102,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) return -EADDRNOTAVAIL;
/* only modify hna-table if it has been initialised before */ - if (atomic_read(&module_state) == MODULE_ACTIVE) { + if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { hna_local_remove(bat_priv, dev->dev_addr, "mac address changed"); hna_local_add(dev, addr->sa_data); @@ -140,7 +131,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) struct bcast_packet *bcast_packet; int data_len = skb->len, ret;
- if (atomic_read(&module_state) != MODULE_ACTIVE) + if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dropped;
soft_iface->trans_start = jiffies; @@ -150,6 +141,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
/* ethernet packet should be broadcasted */ if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) { + if (!bat_priv->primary_if) + goto dropped;
if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) goto dropped; @@ -163,14 +156,14 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
/* hw address of first interface is the orig mac because only * this mac is known throughout the mesh */ - memcpy(bcast_packet->orig, main_if_addr, ETH_ALEN); + memcpy(bcast_packet->orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
/* set broadcast sequence number */ - bcast_packet->seqno = htonl(bcast_seqno); + bcast_packet->seqno = + htonl(atomic_inc_return(&bat_priv->bcast_seqno));
- /* broadcast packet. on success, increase seqno. */ - if (add_bcast_packet_to_list(bat_priv, skb) == NETDEV_TX_OK) - bcast_seqno++; + add_bcast_packet_to_list(bat_priv, skb);
/* a copy is stored in the bcast list, therefore removing * the original skb. */ @@ -179,10 +172,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* unicast packet */ } else { ret = unicast_send_skb(skb, bat_priv); - if (ret != 0) { - bat_priv->stats.tx_dropped++; - goto end; - } + if (ret != 0) + goto dropped_freed; }
bat_priv->stats.tx_packets++; @@ -190,8 +181,9 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) goto end;
dropped: - bat_priv->stats.tx_dropped++; kfree_skb(skb); +dropped_freed: + bat_priv->stats.tx_dropped++; end: return NETDEV_TX_OK; } @@ -292,7 +284,6 @@ struct net_device *softif_create(char *name) }
ret = register_netdev(soft_iface); - if (ret < 0) { pr_err("Unable to register the batman interface '%s': %i\n", name, ret); @@ -310,21 +301,29 @@ struct net_device *softif_create(char *name) atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN); atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
+ atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); + atomic_set(&bat_priv->bcast_seqno, 1); + atomic_set(&bat_priv->hna_local_changed, 0); + bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0;
ret = sysfs_add_meshif(soft_iface); - if (ret < 0) goto unreg_soft_iface;
ret = debugfs_add_meshif(soft_iface); - if (ret < 0) goto unreg_sysfs;
+ ret = mesh_init(soft_iface); + if (ret < 0) + goto unreg_debugfs; + return soft_iface;
+unreg_debugfs: + debugfs_del_meshif(soft_iface); unreg_sysfs: sysfs_del_meshif(soft_iface); unreg_soft_iface: @@ -341,6 +340,7 @@ void softif_destroy(struct net_device *soft_iface) { debugfs_del_meshif(soft_iface); sysfs_del_meshif(soft_iface); + mesh_free(soft_iface); unregister_netdevice(soft_iface); }
diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h index 04f04b4..843a7ec 100644 --- a/drivers/staging/batman-adv/soft-interface.h +++ b/drivers/staging/batman-adv/soft-interface.h @@ -22,7 +22,6 @@ #ifndef _NET_BATMAN_ADV_SOFT_INTERFACE_H_ #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
-void set_main_if_addr(uint8_t *addr); int my_skb_head_push(struct sk_buff *skb, unsigned int len); int interface_tx(struct sk_buff *skb, struct net_device *soft_iface); void interface_rx(struct net_device *soft_iface, @@ -30,6 +29,4 @@ void interface_rx(struct net_device *soft_iface, struct net_device *softif_create(char *name); void softif_destroy(struct net_device *soft_iface);
-extern unsigned char main_if_addr[]; - #endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */ diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 55e5e08..12b2325 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -25,36 +25,29 @@ #include "types.h" #include "hash.h"
-struct hashtable_t *hna_local_hash; -static struct hashtable_t *hna_global_hash; -atomic_t hna_local_changed; - -DEFINE_SPINLOCK(hna_local_hash_lock); -static DEFINE_SPINLOCK(hna_global_hash_lock); - static void hna_local_purge(struct work_struct *work); -static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge); static void _hna_global_del_orig(struct bat_priv *bat_priv, struct hna_global_entry *hna_global_entry, char *message);
-static void hna_local_start_timer(void) +static void hna_local_start_timer(struct bat_priv *bat_priv) { - queue_delayed_work(bat_event_workqueue, &hna_local_purge_wq, 10 * HZ); + INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge); + queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ); }
-int hna_local_init(void) +int hna_local_init(struct bat_priv *bat_priv) { - if (hna_local_hash) + if (bat_priv->hna_local_hash) return 1;
- hna_local_hash = hash_new(128, compare_orig, choose_orig); + bat_priv->hna_local_hash = hash_new(128, compare_orig, choose_orig);
- if (!hna_local_hash) + if (!bat_priv->hna_local_hash) return 0;
- atomic_set(&hna_local_changed, 0); - hna_local_start_timer(); + atomic_set(&bat_priv->hna_local_changed, 0); + hna_local_start_timer(bat_priv);
return 1; } @@ -67,12 +60,13 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr) struct hashtable_t *swaphash; unsigned long flags;
- spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags); hna_local_entry = - ((struct hna_local_entry *)hash_find(hna_local_hash, addr)); - spin_unlock_irqrestore(&hna_local_hash_lock, flags); + ((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash, + addr)); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
- if (hna_local_entry != NULL) { + if (hna_local_entry) { hna_local_entry->last_seen = jiffies; return; } @@ -80,8 +74,9 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr) /* only announce as many hosts as possible in the batman-packet and space in batman_packet->num_hna That also should give a limit to MAC-flooding. */ - if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) || - (num_hna + 1 > 255)) { + if ((bat_priv->num_local_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) + / ETH_ALEN) || + (bat_priv->num_local_hna + 1 > 255)) { bat_dbg(DBG_ROUTES, bat_priv, "Can't add new local hna entry (%pM): " "number of local hna entries exceeds packet size\n", @@ -105,47 +100,49 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr) else hna_local_entry->never_purge = 0;
- spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
- hash_add(hna_local_hash, hna_local_entry); - num_hna++; - atomic_set(&hna_local_changed, 1); + hash_add(bat_priv->hna_local_hash, hna_local_entry); + bat_priv->num_local_hna++; + atomic_set(&bat_priv->hna_local_changed, 1);
- if (hna_local_hash->elements * 4 > hna_local_hash->size) { - swaphash = hash_resize(hna_local_hash, - hna_local_hash->size * 2); + if (bat_priv->hna_local_hash->elements * 4 > + bat_priv->hna_local_hash->size) { + swaphash = hash_resize(bat_priv->hna_local_hash, + bat_priv->hna_local_hash->size * 2);
- if (swaphash == NULL) + if (!swaphash) pr_err("Couldn't resize local hna hash table\n"); else - hna_local_hash = swaphash; + bat_priv->hna_local_hash = swaphash; }
- spin_unlock_irqrestore(&hna_local_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
/* remove address from global hash if present */ - spin_lock_irqsave(&hna_global_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
- hna_global_entry = - ((struct hna_global_entry *)hash_find(hna_global_hash, addr)); + hna_global_entry = ((struct hna_global_entry *) + hash_find(bat_priv->hna_global_hash, addr));
- if (hna_global_entry != NULL) + if (hna_global_entry) _hna_global_del_orig(bat_priv, hna_global_entry, "local hna received");
- spin_unlock_irqrestore(&hna_global_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags); }
-int hna_local_fill_buffer(unsigned char *buff, int buff_len) +int hna_local_fill_buffer(struct bat_priv *bat_priv, + unsigned char *buff, int buff_len) { struct hna_local_entry *hna_local_entry; HASHIT(hashit); int i = 0; unsigned long flags;
- spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
- while (hash_iterate(hna_local_hash, &hashit)) { + while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
if (buff_len < (i + 1) * ETH_ALEN) break; @@ -157,11 +154,10 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) }
/* if we did not get all new local hnas see you next time ;-) */ - if (i == num_hna) - atomic_set(&hna_local_changed, 0); - - spin_unlock_irqrestore(&hna_local_hash_lock, flags); + if (i == bat_priv->num_local_hna) + atomic_set(&bat_priv->hna_local_changed, 0);
+ spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags); return i; }
@@ -186,29 +182,29 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) "announced via HNA:\n", net_dev->name);
- spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ - while (hash_iterate(hna_local_hash, &hashit_count)) + while (hash_iterate(bat_priv->hna_local_hash, &hashit_count)) buf_size += 21;
buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_irqrestore(&hna_local_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags); return -ENOMEM; } buff[0] = '\0'; pos = 0;
- while (hash_iterate(hna_local_hash, &hashit)) { + while (hash_iterate(bat_priv->hna_local_hash, &hashit)) { hna_local_entry = hashit.bucket->data;
pos += snprintf(buff + pos, 22, " * %pM\n", hna_local_entry->addr); }
- spin_unlock_irqrestore(&hna_local_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
seq_printf(seq, "%s", buff); kfree(buff); @@ -217,9 +213,11 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
static void _hna_local_del(void *data, void *arg) { + struct bat_priv *bat_priv = (struct bat_priv *)arg; + kfree(data); - num_hna--; - atomic_set(&hna_local_changed, 1); + bat_priv->num_local_hna--; + atomic_set(&bat_priv->hna_local_changed, 1); }
static void hna_local_del(struct bat_priv *bat_priv, @@ -229,7 +227,7 @@ static void hna_local_del(struct bat_priv *bat_priv, bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", hna_local_entry->addr, message);
- hash_remove(hna_local_hash, hna_local_entry->addr); + hash_remove(bat_priv->hna_local_hash, hna_local_entry->addr); _hna_local_del(hna_local_entry, bat_priv); }
@@ -239,57 +237,62 @@ void hna_local_remove(struct bat_priv *bat_priv, struct hna_local_entry *hna_local_entry; unsigned long flags;
- spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
hna_local_entry = (struct hna_local_entry *) - hash_find(hna_local_hash, addr); + hash_find(bat_priv->hna_local_hash, addr); if (hna_local_entry) hna_local_del(bat_priv, hna_local_entry, message);
- spin_unlock_irqrestore(&hna_local_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags); }
static void hna_local_purge(struct work_struct *work) { + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct bat_priv *bat_priv = + container_of(delayed_work, struct bat_priv, hna_work); struct hna_local_entry *hna_local_entry; HASHIT(hashit); unsigned long flags; unsigned long timeout;
- spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
- while (hash_iterate(hna_local_hash, &hashit)) { + while (hash_iterate(bat_priv->hna_local_hash, &hashit)) { hna_local_entry = hashit.bucket->data;
timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ; - /* if ((!hna_local_entry->never_purge) && + + if ((!hna_local_entry->never_purge) && time_after(jiffies, timeout)) hna_local_del(bat_priv, hna_local_entry, - "address timed out");*/ + "address timed out"); }
- spin_unlock_irqrestore(&hna_local_hash_lock, flags); - hna_local_start_timer(); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags); + hna_local_start_timer(bat_priv); }
-void hna_local_free(void) +void hna_local_free(struct bat_priv *bat_priv) { - if (!hna_local_hash) + if (!bat_priv->hna_local_hash) return;
- cancel_delayed_work_sync(&hna_local_purge_wq); - hash_delete(hna_local_hash, _hna_local_del, NULL); - hna_local_hash = NULL; + cancel_delayed_work_sync(&bat_priv->hna_work); + hash_delete(bat_priv->hna_local_hash, _hna_local_del, bat_priv); + bat_priv->hna_local_hash = NULL; }
-int hna_global_init(void) +int hna_global_init(struct bat_priv *bat_priv) { - if (hna_global_hash) + if (bat_priv->hna_global_hash) return 1;
- hna_global_hash = hash_new(128, compare_orig, choose_orig); + bat_priv->hna_global_hash = hash_new(128, compare_orig, choose_orig);
- if (!hna_global_hash) + if (!bat_priv->hna_global_hash) return 0;
return 1; @@ -307,14 +310,15 @@ void hna_global_add_orig(struct bat_priv *bat_priv, unsigned char *hna_ptr;
while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { - spin_lock_irqsave(&hna_global_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); hna_global_entry = (struct hna_global_entry *) - hash_find(hna_global_hash, hna_ptr); + hash_find(bat_priv->hna_global_hash, hna_ptr);
- if (hna_global_entry == NULL) { - spin_unlock_irqrestore(&hna_global_hash_lock, flags); + if (!hna_global_entry) { + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, + flags);
hna_global_entry = kmalloc(sizeof(struct hna_global_entry), @@ -330,26 +334,26 @@ void hna_global_add_orig(struct bat_priv *bat_priv, "%pM (via %pM)\n", hna_global_entry->addr, orig_node->orig);
- spin_lock_irqsave(&hna_global_hash_lock, flags); - hash_add(hna_global_hash, hna_global_entry); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags); + hash_add(bat_priv->hna_global_hash, hna_global_entry);
}
hna_global_entry->orig_node = orig_node; - spin_unlock_irqrestore(&hna_global_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
/* remove address from local hash if present */ - spin_lock_irqsave(&hna_local_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); hna_local_entry = (struct hna_local_entry *) - hash_find(hna_local_hash, hna_ptr); + hash_find(bat_priv->hna_local_hash, hna_ptr);
- if (hna_local_entry != NULL) + if (hna_local_entry) hna_local_del(bat_priv, hna_local_entry, "global hna received");
- spin_unlock_irqrestore(&hna_local_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
hna_buff_count++; } @@ -366,19 +370,20 @@ void hna_global_add_orig(struct bat_priv *bat_priv, } }
- spin_lock_irqsave(&hna_global_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
- if (hna_global_hash->elements * 4 > hna_global_hash->size) { - swaphash = hash_resize(hna_global_hash, - hna_global_hash->size * 2); + if (bat_priv->hna_global_hash->elements * 4 > + bat_priv->hna_global_hash->size) { + swaphash = hash_resize(bat_priv->hna_global_hash, + bat_priv->hna_global_hash->size * 2);
- if (swaphash == NULL) + if (!swaphash) pr_err("Couldn't resize global hna hash table\n"); else - hna_global_hash = swaphash; + bat_priv->hna_global_hash = swaphash; }
- spin_unlock_irqrestore(&hna_global_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags); }
int hna_global_seq_print_text(struct seq_file *seq, void *offset) @@ -401,22 +406,22 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", net_dev->name);
- spin_lock_irqsave(&hna_global_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ - while (hash_iterate(hna_global_hash, &hashit_count)) + while (hash_iterate(bat_priv->hna_global_hash, &hashit_count)) buf_size += 43;
buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_irqrestore(&hna_global_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags); return -ENOMEM; } buff[0] = '\0'; pos = 0;
- while (hash_iterate(hna_global_hash, &hashit)) { + while (hash_iterate(bat_priv->hna_global_hash, &hashit)) { hna_global_entry = hashit.bucket->data;
pos += snprintf(buff + pos, 44, @@ -424,7 +429,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) hna_global_entry->orig_node->orig); }
- spin_unlock_irqrestore(&hna_global_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
seq_printf(seq, "%s", buff); kfree(buff); @@ -440,7 +445,7 @@ static void _hna_global_del_orig(struct bat_priv *bat_priv, hna_global_entry->addr, hna_global_entry->orig_node->orig, message);
- hash_remove(hna_global_hash, hna_global_entry->addr); + hash_remove(bat_priv->hna_global_hash, hna_global_entry->addr); kfree(hna_global_entry); }
@@ -455,14 +460,14 @@ void hna_global_del_orig(struct bat_priv *bat_priv, if (orig_node->hna_buff_len == 0) return;
- spin_lock_irqsave(&hna_global_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); hna_global_entry = (struct hna_global_entry *) - hash_find(hna_global_hash, hna_ptr); + hash_find(bat_priv->hna_global_hash, hna_ptr);
- if ((hna_global_entry != NULL) && + if ((hna_global_entry) && (hna_global_entry->orig_node == orig_node)) _hna_global_del_orig(bat_priv, hna_global_entry, message); @@ -470,7 +475,7 @@ void hna_global_del_orig(struct bat_priv *bat_priv, hna_buff_count++; }
- spin_unlock_irqrestore(&hna_global_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
orig_node->hna_buff_len = 0; kfree(orig_node->hna_buff); @@ -482,26 +487,26 @@ static void hna_global_del(void *data, void *arg) kfree(data); }
-void hna_global_free(void) +void hna_global_free(struct bat_priv *bat_priv) { - if (!hna_global_hash) + if (!bat_priv->hna_global_hash) return;
- hash_delete(hna_global_hash, hna_global_del, NULL); - hna_global_hash = NULL; + hash_delete(bat_priv->hna_global_hash, hna_global_del, NULL); + bat_priv->hna_global_hash = NULL; }
-struct orig_node *transtable_search(uint8_t *addr) +struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) { struct hna_global_entry *hna_global_entry; unsigned long flags;
- spin_lock_irqsave(&hna_global_hash_lock, flags); + spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags); hna_global_entry = (struct hna_global_entry *) - hash_find(hna_global_hash, addr); - spin_unlock_irqrestore(&hna_global_hash_lock, flags); + hash_find(bat_priv->hna_global_hash, addr); + spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
- if (hna_global_entry == NULL) + if (!hna_global_entry) return NULL;
return hna_global_entry->orig_node; diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h index af7a59c..10c4c5c 100644 --- a/drivers/staging/batman-adv/translation-table.h +++ b/drivers/staging/batman-adv/translation-table.h @@ -24,25 +24,22 @@
#include "types.h"
-int hna_local_init(void); +int hna_local_init(struct bat_priv *bat_priv); void hna_local_add(struct net_device *soft_iface, uint8_t *addr); void hna_local_remove(struct bat_priv *bat_priv, uint8_t *addr, char *message); -int hna_local_fill_buffer(unsigned char *buff, int buff_len); +int hna_local_fill_buffer(struct bat_priv *bat_priv, + unsigned char *buff, int buff_len); int hna_local_seq_print_text(struct seq_file *seq, void *offset); -void hna_local_free(void); -int hna_global_init(void); +void hna_local_free(struct bat_priv *bat_priv); +int hna_global_init(struct bat_priv *bat_priv); void hna_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, unsigned char *hna_buff, int hna_buff_len); int hna_global_seq_print_text(struct seq_file *seq, void *offset); void hna_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, char *message); -void hna_global_free(void); -struct orig_node *transtable_search(uint8_t *addr); - -extern spinlock_t hna_local_hash_lock; -extern struct hashtable_t *hna_local_hash; -extern atomic_t hna_local_changed; +void hna_global_free(struct bat_priv *bat_priv); +struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr);
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index c5b738d..b4f2b0c 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -51,18 +51,18 @@ struct batman_if { };
/** - * orig_node - structure for orig_list maintaining nodes of mesh - * @primary_addr: hosts primary interface address - * @last_valid: when last packet from this node was received - * @bcast_seqno_reset: time when the broadcast seqno window was reset - * @batman_seqno_reset: time when the batman seqno window was reset - * @flags: for now only VIS_SERVER flag - * @last_real_seqno: last and best known squence number - * @last_ttl: ttl of last received packet - * @last_bcast_seqno: last broadcast sequence number received by this host - * - * @candidates: how many candidates are available - * @selected: next bonding candidate + * orig_node - structure for orig_list maintaining nodes of mesh + * @primary_addr: hosts primary interface address + * @last_valid: when last packet from this node was received + * @bcast_seqno_reset: time when the broadcast seqno window was reset + * @batman_seqno_reset: time when the batman seqno window was reset + * @flags: for now only VIS_SERVER flag + * @last_real_seqno: last and best known squence number + * @last_ttl: ttl of last received packet + * @last_bcast_seqno: last broadcast sequence number received by this host + * + * @candidates: how many candidates are available + * @selected: next bonding candidate */ struct orig_node { uint8_t orig[ETH_ALEN]; @@ -92,8 +92,8 @@ struct orig_node { };
/** - * neigh_node - * @last_valid: when last packet via this neighbor was received + * neigh_node + * @last_valid: when last packet via this neighbor was received */ struct neigh_node { struct list_head list; @@ -111,6 +111,7 @@ struct neigh_node { };
struct bat_priv { + atomic_t mesh_state; struct net_device_stats stats; atomic_t aggregation_enabled; atomic_t bonding_enabled; @@ -118,6 +119,7 @@ struct bat_priv { atomic_t vis_mode; atomic_t orig_interval; atomic_t log_level; + atomic_t bcast_seqno; atomic_t bcast_queue_left; atomic_t batman_queue_left; char num_ifaces; @@ -125,6 +127,29 @@ struct bat_priv { struct batman_if *primary_if; struct kobject *mesh_obj; struct dentry *debug_dir; + struct hlist_head forw_bat_list; + struct hlist_head forw_bcast_list; + struct hlist_head gw_list; + struct list_head vis_send_list; + struct hashtable_t *orig_hash; + struct hashtable_t *hna_local_hash; + struct hashtable_t *hna_global_hash; + struct hashtable_t *vis_hash; + spinlock_t orig_hash_lock; + spinlock_t forw_bat_list_lock; + spinlock_t forw_bcast_list_lock; + spinlock_t hna_lhash_lock; + spinlock_t hna_ghash_lock; + spinlock_t gw_list_lock; + spinlock_t vis_hash_lock; + spinlock_t vis_list_lock; + int16_t num_local_hna; + atomic_t hna_local_changed; + struct delayed_work hna_work; + struct delayed_work orig_work; + struct delayed_work vis_work; + struct gw_node *curr_gw; + struct vis_info *my_vis_info; };
struct socket_client { @@ -154,8 +179,8 @@ struct hna_global_entry { };
/** - * forw_packet - structure for forw_list maintaining packets to be - * send/forwarded + * forw_packet - structure for forw_list maintaining packets to be + * send/forwarded */ struct forw_packet { struct hlist_node list; @@ -193,4 +218,28 @@ struct frag_packet_list_entry { struct sk_buff *skb; };
+struct vis_info { + unsigned long first_seen; + struct list_head recv_list; + /* list of server-neighbors we received a vis-packet + * from. we should not reply to them. */ + struct list_head send_list; + struct kref refcount; + struct bat_priv *bat_priv; + /* this packet might be part of the vis send queue. */ + struct sk_buff *skb_packet; + /* vis_info may follow here*/ +} __attribute__((packed)); + +struct vis_info_entry { + uint8_t src[ETH_ALEN]; + uint8_t dest[ETH_ALEN]; + uint8_t quality; /* quality = 0 means HNA */ +} __attribute__((packed)); + +struct recvlist_node { + struct list_head list; + uint8_t mac[ETH_ALEN]; +}; + #endif /* _NET_BATMAN_ADV_TYPES_H_ */ diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c index 61ebd38..f951abc 100644 --- a/drivers/staging/batman-adv/unicast.c +++ b/drivers/staging/batman-adv/unicast.c @@ -34,7 +34,7 @@ struct sk_buff *merge_frag_packet(struct list_head *head, struct sk_buff *skb) { struct unicast_frag_packet *up = - (struct unicast_frag_packet *) skb->data; + (struct unicast_frag_packet *)skb->data; struct sk_buff *tmp_skb;
/* set skb to the first part and tmp_skb to the second part */ @@ -66,7 +66,7 @@ void create_frag_entry(struct list_head *head, struct sk_buff *skb) { struct frag_packet_list_entry *tfp; struct unicast_frag_packet *up = - (struct unicast_frag_packet *) skb->data; + (struct unicast_frag_packet *)skb->data;
/* free and oldest packets stand at the end */ tfp = list_entry((head)->prev, typeof(*tfp), list); @@ -115,7 +115,7 @@ struct frag_packet_list_entry *search_frag_packet(struct list_head *head, if (tfp->seqno == ntohs(up->seqno)) goto mov_tail;
- tmp_up = (struct unicast_frag_packet *) tfp->skb->data; + tmp_up = (struct unicast_frag_packet *)tfp->skb->data;
if (tfp->seqno == search_seqno) {
@@ -210,14 +210,15 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) uint8_t dstaddr[6]; unsigned long flags;
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
/* get routing information */ - orig_node = ((struct orig_node *)hash_find(orig_hash, ethhdr->h_dest)); + orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, + ethhdr->h_dest));
/* check for hna host */ if (!orig_node) - orig_node = transtable_search(ethhdr->h_dest); + orig_node = transtable_search(bat_priv, ethhdr->h_dest);
router = find_router(orig_node, NULL);
@@ -230,7 +231,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) batman_if = router->if_incoming; memcpy(dstaddr, router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
if (batman_if->if_status != IF_ACTIVE) goto dropped; @@ -257,7 +258,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) return 0;
unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); dropped: kfree_skb(skb); return 1; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index ad899fe..071d3b7 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -27,6 +27,8 @@ #include "hard-interface.h" #include "hash.h"
+#define MAX_VIS_PACKET_SIZE 1000 + /* Returns the smallest signed integer in two's complement with the sizeof x */ #define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
@@ -43,32 +45,25 @@ _dummy > smallest_signed_int(_dummy); }) #define seq_after(x, y) seq_before(y, x)
-#define MAX_VIS_PACKET_SIZE 1000 - -static struct hashtable_t *vis_hash; -static DEFINE_SPINLOCK(vis_hash_lock); -static DEFINE_SPINLOCK(recv_list_lock); -static struct vis_info *my_vis_info; -static struct list_head send_list; /* always locked with vis_hash_lock */ - -static void start_vis_timer(void); +static void start_vis_timer(struct bat_priv *bat_priv);
/* free the info */ static void free_info(struct kref *ref) { struct vis_info *info = container_of(ref, struct vis_info, refcount); + struct bat_priv *bat_priv = info->bat_priv; struct recvlist_node *entry, *tmp; unsigned long flags;
list_del_init(&info->send_list); - spin_lock_irqsave(&recv_list_lock, flags); + spin_lock_irqsave(&bat_priv->vis_list_lock, flags); list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { list_del(&entry->list); kfree(entry); } - spin_unlock_irqrestore(&recv_list_lock, flags); + + spin_unlock_irqrestore(&bat_priv->vis_list_lock, flags); kfree_skb(info->skb_packet); - kfree(info); }
/* Compare two vis packets, used by the hashing algorithm */ @@ -207,8 +202,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
buf_size = 1; /* Estimate length */ - spin_lock_irqsave(&vis_hash_lock, flags); - while (hash_iterate(vis_hash, &hashit_count)) { + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); + while (hash_iterate(bat_priv->vis_hash, &hashit_count)) { info = hashit_count.bucket->data; packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) @@ -240,13 +235,13 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_irqrestore(&vis_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); return -ENOMEM; } buff[0] = '\0'; buff_pos = 0;
- while (hash_iterate(vis_hash, &hashit)) { + while (hash_iterate(bat_priv->vis_hash, &hashit)) { info = hashit.bucket->data; packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) @@ -285,7 +280,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) } }
- spin_unlock_irqrestore(&vis_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags);
seq_printf(seq, "%s", buff); kfree(buff); @@ -295,11 +290,11 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
/* add the info packet to the send list, if it was not * already linked in. */ -static void send_list_add(struct vis_info *info) +static void send_list_add(struct bat_priv *bat_priv, struct vis_info *info) { if (list_empty(&info->send_list)) { kref_get(&info->refcount); - list_add_tail(&info->send_list, &send_list); + list_add_tail(&info->send_list, &bat_priv->vis_send_list); } }
@@ -314,7 +309,8 @@ static void send_list_del(struct vis_info *info) }
/* tries to add one entry to the receive list. */ -static void recv_list_add(struct list_head *recv_list, char *mac) +static void recv_list_add(struct bat_priv *bat_priv, + struct list_head *recv_list, char *mac) { struct recvlist_node *entry; unsigned long flags; @@ -324,32 +320,35 @@ static void recv_list_add(struct list_head *recv_list, char *mac) return;
memcpy(entry->mac, mac, ETH_ALEN); - spin_lock_irqsave(&recv_list_lock, flags); + spin_lock_irqsave(&bat_priv->vis_list_lock, flags); list_add_tail(&entry->list, recv_list); - spin_unlock_irqrestore(&recv_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_list_lock, flags); }
/* returns 1 if this mac is in the recv_list */ -static int recv_list_is_in(struct list_head *recv_list, char *mac) +static int recv_list_is_in(struct bat_priv *bat_priv, + struct list_head *recv_list, char *mac) { struct recvlist_node *entry; unsigned long flags;
- spin_lock_irqsave(&recv_list_lock, flags); + spin_lock_irqsave(&bat_priv->vis_list_lock, flags); list_for_each_entry(entry, recv_list, list) { if (memcmp(entry->mac, mac, ETH_ALEN) == 0) { - spin_unlock_irqrestore(&recv_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_list_lock, + flags); return 1; } } - spin_unlock_irqrestore(&recv_list_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_list_lock, flags); return 0; }
/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old, * broken.. ). vis hash must be locked outside. is_new is set when the packet * is newer than old entries in the hash. */ -static struct vis_info *add_packet(struct vis_packet *vis_packet, +static struct vis_info *add_packet(struct bat_priv *bat_priv, + struct vis_packet *vis_packet, int vis_info_len, int *is_new, int make_broadcast) { @@ -360,7 +359,7 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
*is_new = 0; /* sanity check */ - if (vis_hash == NULL) + if (!bat_priv->vis_hash) return NULL;
/* see if the packet is already in vis_hash */ @@ -371,15 +370,15 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, sizeof(struct vis_packet));
memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); - old_info = hash_find(vis_hash, &search_elem); + old_info = hash_find(bat_priv->vis_hash, &search_elem); kfree_skb(search_elem.skb_packet);
if (old_info != NULL) { old_packet = (struct vis_packet *)old_info->skb_packet->data; if (!seq_after(ntohl(vis_packet->seqno), - ntohl(old_packet->seqno))) { + ntohl(old_packet->seqno))) { if (old_packet->seqno == vis_packet->seqno) { - recv_list_add(&old_info->recv_list, + recv_list_add(bat_priv, &old_info->recv_list, vis_packet->sender_orig); return old_info; } else { @@ -388,13 +387,13 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, } } /* remove old entry */ - hash_remove(vis_hash, old_info); + hash_remove(bat_priv->vis_hash, old_info); send_list_del(old_info); kref_put(&old_info->refcount, free_info); }
info = kmalloc(sizeof(struct vis_info), GFP_ATOMIC); - if (info == NULL) + if (!info) return NULL;
info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) + @@ -412,6 +411,7 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, INIT_LIST_HEAD(&info->send_list); INIT_LIST_HEAD(&info->recv_list); info->first_seen = jiffies; + info->bat_priv = bat_priv; memcpy(packet, vis_packet, sizeof(struct vis_packet) + vis_info_len);
/* initialize and add new packet. */ @@ -425,10 +425,10 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet, if (packet->entries * sizeof(struct vis_info_entry) > vis_info_len) packet->entries = vis_info_len / sizeof(struct vis_info_entry);
- recv_list_add(&info->recv_list, packet->sender_orig); + recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
/* try to add it */ - if (hash_add(vis_hash, info) < 0) { + if (hash_add(bat_priv->vis_hash, info) < 0) { /* did not work (for some reason) */ kref_put(&old_info->refcount, free_info); info = NULL; @@ -449,17 +449,18 @@ void receive_server_sync_packet(struct bat_priv *bat_priv,
make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC);
- spin_lock_irqsave(&vis_hash_lock, flags); - info = add_packet(vis_packet, vis_info_len, &is_new, make_broadcast); - if (info == NULL) + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); + info = add_packet(bat_priv, vis_packet, vis_info_len, + &is_new, make_broadcast); + if (!info) goto end;
/* only if we are server ourselves and packet is newer than the one in * hash.*/ if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) - send_list_add(info); + send_list_add(bat_priv, info); end: - spin_unlock_irqrestore(&vis_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); }
/* handle an incoming client update packet and schedule forward if needed. */ @@ -483,10 +484,11 @@ void receive_client_update_packet(struct bat_priv *bat_priv, is_my_mac(vis_packet->target_orig)) are_target = 1;
- spin_lock_irqsave(&vis_hash_lock, flags); - info = add_packet(vis_packet, vis_info_len, &is_new, are_target); + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); + info = add_packet(bat_priv, vis_packet, vis_info_len, + &is_new, are_target);
- if (info == NULL) + if (!info) goto end; /* note that outdated packets will be dropped at this point. */
@@ -495,22 +497,23 @@ void receive_client_update_packet(struct bat_priv *bat_priv, /* send only if we're the target server or ... */ if (are_target && is_new) { packet->vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ - send_list_add(info); + send_list_add(bat_priv, info);
/* ... we're not the recipient (and thus need to forward). */ } else if (!is_my_mac(packet->target_orig)) { - send_list_add(info); + send_list_add(bat_priv, info); }
end: - spin_unlock_irqrestore(&vis_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); }
/* Walk the originators and find the VIS server with the best tq. Set the packet * address to its address and return the best_tq. * * Must be called with the originator hash locked */ -static int find_best_vis_server(struct vis_info *info) +static int find_best_vis_server(struct bat_priv *bat_priv, + struct vis_info *info) { HASHIT(hashit); struct orig_node *orig_node; @@ -519,10 +522,9 @@ static int find_best_vis_server(struct vis_info *info)
packet = (struct vis_packet *)info->skb_packet->data;
- while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) { orig_node = hashit.bucket->data; - if ((orig_node != NULL) && - (orig_node->router != NULL) && + if ((orig_node) && (orig_node->router) && (orig_node->flags & VIS_SERVER) && (orig_node->router->tq_avg > best_tq)) { best_tq = orig_node->router->tq_avg; @@ -551,7 +553,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) HASHIT(hashit_local); HASHIT(hashit_global); struct orig_node *orig_node; - struct vis_info *info = (struct vis_info *)my_vis_info; + struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_info_entry *entry; struct hna_local_entry *hna_local_entry; @@ -561,7 +563,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) info->first_seen = jiffies; packet->vis_type = atomic_read(&bat_priv->vis_mode);
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); memcpy(packet->target_orig, broadcast_addr, ETH_ALEN); packet->ttl = TTL; packet->seqno = htonl(ntohl(packet->seqno) + 1); @@ -569,43 +571,51 @@ static int generate_vis_packet(struct bat_priv *bat_priv) skb_trim(info->skb_packet, sizeof(struct vis_packet));
if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) { - best_tq = find_best_vis_server(info); + best_tq = find_best_vis_server(bat_priv, info); + if (best_tq < 0) { - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, + flags); return -1; } }
- while (hash_iterate(orig_hash, &hashit_global)) { + while (hash_iterate(bat_priv->orig_hash, &hashit_global)) { orig_node = hashit_global.bucket->data; - if (orig_node->router != NULL - && compare_orig(orig_node->router->addr, - orig_node->orig) - && (orig_node->router->if_incoming->if_status == - IF_ACTIVE) - && orig_node->router->tq_avg > 0) { - - /* fill one entry into buffer. */ - entry = (struct vis_info_entry *) + + if (!orig_node->router) + continue; + + if (!compare_orig(orig_node->router->addr, orig_node->orig)) + continue; + + if (orig_node->router->if_incoming->if_status != IF_ACTIVE) + continue; + + if (orig_node->router->tq_avg < 1) + continue; + + /* fill one entry into buffer. */ + entry = (struct vis_info_entry *) skb_put(info->skb_packet, sizeof(*entry)); - memcpy(entry->src, - orig_node->router->if_incoming->net_dev->dev_addr, - ETH_ALEN); - memcpy(entry->dest, orig_node->orig, ETH_ALEN); - entry->quality = orig_node->router->tq_avg; - packet->entries++; + memcpy(entry->src, + orig_node->router->if_incoming->net_dev->dev_addr, + ETH_ALEN); + memcpy(entry->dest, orig_node->orig, ETH_ALEN); + entry->quality = orig_node->router->tq_avg; + packet->entries++;
- if (vis_packet_full(info)) { - spin_unlock_irqrestore(&orig_hash_lock, flags); - return 0; - } + if (vis_packet_full(info)) { + spin_unlock_irqrestore( + &bat_priv->orig_hash_lock, flags); + return 0; } }
- spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
- spin_lock_irqsave(&hna_local_hash_lock, flags); - while (hash_iterate(hna_local_hash, &hashit_local)) { + spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags); + while (hash_iterate(bat_priv->hna_local_hash, &hashit_local)) { hna_local_entry = hashit_local.bucket->data; entry = (struct vis_info_entry *)skb_put(info->skb_packet, sizeof(*entry)); @@ -615,35 +625,41 @@ static int generate_vis_packet(struct bat_priv *bat_priv) packet->entries++;
if (vis_packet_full(info)) { - spin_unlock_irqrestore(&hna_local_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, + flags); return 0; } } - spin_unlock_irqrestore(&hna_local_hash_lock, flags); + + spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags); return 0; }
/* free old vis packets. Must be called with this vis_hash_lock * held */ -static void purge_vis_packets(void) +static void purge_vis_packets(struct bat_priv *bat_priv) { HASHIT(hashit); struct vis_info *info;
- while (hash_iterate(vis_hash, &hashit)) { + while (hash_iterate(bat_priv->vis_hash, &hashit)) { info = hashit.bucket->data; - if (info == my_vis_info) /* never purge own data. */ + + /* never purge own data. */ + if (info == bat_priv->my_vis_info) continue; + if (time_after(jiffies, info->first_seen + VIS_TIMEOUT * HZ)) { - hash_remove_bucket(vis_hash, &hashit); + hash_remove_bucket(bat_priv->vis_hash, &hashit); send_list_del(info); kref_put(&info->refcount, free_info); } } }
-static void broadcast_vis_packet(struct vis_info *info) +static void broadcast_vis_packet(struct bat_priv *bat_priv, + struct vis_info *info) { HASHIT(hashit); struct orig_node *orig_node; @@ -653,11 +669,12 @@ static void broadcast_vis_packet(struct vis_info *info) struct batman_if *batman_if; uint8_t dstaddr[ETH_ALEN];
- spin_lock_irqsave(&orig_hash_lock, flags); + + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); packet = (struct vis_packet *)info->skb_packet->data;
/* send to all routers in range. */ - while (hash_iterate(orig_hash, &hashit)) { + while (hash_iterate(bat_priv->orig_hash, &hashit)) { orig_node = hashit.bucket->data;
/* if it's a vis server and reachable, send it. */ @@ -667,26 +684,28 @@ static void broadcast_vis_packet(struct vis_info *info) continue; /* don't send it if we already received the packet from * this node. */ - if (recv_list_is_in(&info->recv_list, orig_node->orig)) + if (recv_list_is_in(bat_priv, &info->recv_list, + orig_node->orig)) continue;
memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (skb) send_skb_packet(skb, batman_if, dstaddr);
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
} - spin_unlock_irqrestore(&orig_hash_lock, flags); - memcpy(packet->target_orig, broadcast_addr, ETH_ALEN); + + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); }
-static void unicast_vis_packet(struct vis_info *info) +static void unicast_vis_packet(struct bat_priv *bat_priv, + struct vis_info *info) { struct orig_node *orig_node; struct sk_buff *skb; @@ -695,9 +714,9 @@ static void unicast_vis_packet(struct vis_info *info) struct batman_if *batman_if; uint8_t dstaddr[ETH_ALEN];
- spin_lock_irqsave(&orig_hash_lock, flags); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); packet = (struct vis_packet *)info->skb_packet->data; - orig_node = ((struct orig_node *)hash_find(orig_hash, + orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, packet->target_orig));
if ((!orig_node) || (!orig_node->router)) @@ -707,7 +726,7 @@ static void unicast_vis_packet(struct vis_info *info) * copy the required data before sending */ batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (skb) @@ -716,11 +735,11 @@ static void unicast_vis_packet(struct vis_info *info) return;
out: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); }
/* only send one vis packet. called from send_vis_packets() */ -static void send_vis_packet(struct vis_info *info) +static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { struct vis_packet *packet;
@@ -730,113 +749,120 @@ static void send_vis_packet(struct vis_info *info) return; }
- memcpy(packet->sender_orig, main_if_addr, ETH_ALEN); + memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, + ETH_ALEN); packet->ttl--;
if (is_bcast(packet->target_orig)) - broadcast_vis_packet(info); + broadcast_vis_packet(bat_priv, info); else - unicast_vis_packet(info); + unicast_vis_packet(bat_priv, info); packet->ttl++; /* restore TTL */ }
/* called from timer; send (and maybe generate) vis packet. */ static void send_vis_packets(struct work_struct *work) { + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct bat_priv *bat_priv = + container_of(delayed_work, struct bat_priv, vis_work); struct vis_info *info, *temp; unsigned long flags; - /* struct bat_priv *bat_priv = netdev_priv(soft_device); */
- spin_lock_irqsave(&vis_hash_lock, flags); + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); + purge_vis_packets(bat_priv);
- purge_vis_packets(); - - /* if (generate_vis_packet(bat_priv) == 0) {*/ + if (generate_vis_packet(bat_priv) == 0) { /* schedule if generation was successful */ - /*send_list_add(my_vis_info); - } */ + send_list_add(bat_priv, bat_priv->my_vis_info); + }
- list_for_each_entry_safe(info, temp, &send_list, send_list) { + list_for_each_entry_safe(info, temp, &bat_priv->vis_send_list, + send_list) {
kref_get(&info->refcount); - spin_unlock_irqrestore(&vis_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags);
- send_vis_packet(info); + if (bat_priv->primary_if) + send_vis_packet(bat_priv, info);
- spin_lock_irqsave(&vis_hash_lock, flags); + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); send_list_del(info); kref_put(&info->refcount, free_info); } - spin_unlock_irqrestore(&vis_hash_lock, flags); - start_vis_timer(); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); + start_vis_timer(bat_priv); } -static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets);
/* init the vis server. this may only be called when if_list is already * initialized (e.g. bat0 is initialized, interfaces have been added) */ -int vis_init(void) +int vis_init(struct bat_priv *bat_priv) { struct vis_packet *packet; unsigned long flags; - if (vis_hash) + + if (bat_priv->vis_hash) return 1;
- spin_lock_irqsave(&vis_hash_lock, flags); + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags);
- vis_hash = hash_new(256, vis_info_cmp, vis_info_choose); - if (!vis_hash) { + bat_priv->vis_hash = hash_new(256, vis_info_cmp, vis_info_choose); + if (!bat_priv->vis_hash) { pr_err("Can't initialize vis_hash\n"); goto err; }
- my_vis_info = kmalloc(MAX_VIS_PACKET_SIZE, GFP_ATOMIC); - if (!my_vis_info) { + bat_priv->my_vis_info = kmalloc(MAX_VIS_PACKET_SIZE, GFP_ATOMIC); + if (!bat_priv->my_vis_info) { pr_err("Can't initialize vis packet\n"); goto err; }
- my_vis_info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) + + bat_priv->my_vis_info->skb_packet = dev_alloc_skb( + sizeof(struct vis_packet) + MAX_VIS_PACKET_SIZE + sizeof(struct ethhdr)); - if (!my_vis_info->skb_packet) + if (!bat_priv->my_vis_info->skb_packet) goto free_info; - skb_reserve(my_vis_info->skb_packet, sizeof(struct ethhdr)); - packet = (struct vis_packet *)skb_put(my_vis_info->skb_packet, - sizeof(struct vis_packet)); + + skb_reserve(bat_priv->my_vis_info->skb_packet, sizeof(struct ethhdr)); + packet = (struct vis_packet *)skb_put( + bat_priv->my_vis_info->skb_packet, + sizeof(struct vis_packet));
/* prefill the vis info */ - my_vis_info->first_seen = jiffies - msecs_to_jiffies(VIS_INTERVAL); - INIT_LIST_HEAD(&my_vis_info->recv_list); - INIT_LIST_HEAD(&my_vis_info->send_list); - kref_init(&my_vis_info->refcount); + bat_priv->my_vis_info->first_seen = jiffies - + msecs_to_jiffies(VIS_INTERVAL); + INIT_LIST_HEAD(&bat_priv->my_vis_info->recv_list); + INIT_LIST_HEAD(&bat_priv->my_vis_info->send_list); + kref_init(&bat_priv->my_vis_info->refcount); + bat_priv->my_vis_info->bat_priv = bat_priv; packet->version = COMPAT_VERSION; packet->packet_type = BAT_VIS; packet->ttl = TTL; packet->seqno = 0; packet->entries = 0;
- INIT_LIST_HEAD(&send_list); + INIT_LIST_HEAD(&bat_priv->vis_send_list);
- memcpy(packet->vis_orig, main_if_addr, ETH_ALEN); - memcpy(packet->sender_orig, main_if_addr, ETH_ALEN); - - if (hash_add(vis_hash, my_vis_info) < 0) { + if (hash_add(bat_priv->vis_hash, bat_priv->my_vis_info) < 0) { pr_err("Can't add own vis packet into hash\n"); /* not in hash, need to remove it manually. */ - kref_put(&my_vis_info->refcount, free_info); + kref_put(&bat_priv->my_vis_info->refcount, free_info); goto err; }
- spin_unlock_irqrestore(&vis_hash_lock, flags); - start_vis_timer(); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); + start_vis_timer(bat_priv); return 1;
free_info: - kfree(my_vis_info); - my_vis_info = NULL; + kfree(bat_priv->my_vis_info); + bat_priv->my_vis_info = NULL; err: - spin_unlock_irqrestore(&vis_hash_lock, flags); - vis_quit(); + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); + vis_quit(bat_priv); return 0; }
@@ -850,25 +876,26 @@ static void free_info_ref(void *data, void *arg) }
/* shutdown vis-server */ -void vis_quit(void) +void vis_quit(struct bat_priv *bat_priv) { unsigned long flags; - if (!vis_hash) + if (!bat_priv->vis_hash) return;
- cancel_delayed_work_sync(&vis_timer_wq); + cancel_delayed_work_sync(&bat_priv->vis_work);
- spin_lock_irqsave(&vis_hash_lock, flags); + spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); /* properly remove, kill timers ... */ - hash_delete(vis_hash, free_info_ref, NULL); - vis_hash = NULL; - my_vis_info = NULL; - spin_unlock_irqrestore(&vis_hash_lock, flags); + hash_delete(bat_priv->vis_hash, free_info_ref, NULL); + bat_priv->vis_hash = NULL; + bat_priv->my_vis_info = NULL; + spin_unlock_irqrestore(&bat_priv->vis_hash_lock, flags); }
/* schedule packets for (re)transmission */ -static void start_vis_timer(void) +static void start_vis_timer(struct bat_priv *bat_priv) { - queue_delayed_work(bat_event_workqueue, &vis_timer_wq, - (VIS_INTERVAL * HZ) / 1000); + INIT_DELAYED_WORK(&bat_priv->vis_work, send_vis_packets); + queue_delayed_work(bat_event_workqueue, &bat_priv->vis_work, + msecs_to_jiffies(VIS_INTERVAL)); } diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index 19dc325..2c3b330 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -24,29 +24,6 @@
#define VIS_TIMEOUT 200 /* timeout of vis packets in seconds */
-struct vis_info { - unsigned long first_seen; - struct list_head recv_list; - /* list of server-neighbors we received a vis-packet - * from. we should not reply to them. */ - struct list_head send_list; - struct kref refcount; - /* this packet might be part of the vis send queue. */ - struct sk_buff *skb_packet; - /* vis_info may follow here*/ -} __attribute__((packed)); - -struct vis_info_entry { - uint8_t src[ETH_ALEN]; - uint8_t dest[ETH_ALEN]; - uint8_t quality; /* quality = 0 means HNA */ -} __attribute__((packed)); - -struct recvlist_node { - struct list_head list; - uint8_t mac[ETH_ALEN]; -}; - int vis_seq_print_text(struct seq_file *seq, void *offset); void receive_server_sync_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, @@ -54,7 +31,7 @@ void receive_server_sync_packet(struct bat_priv *bat_priv, void receive_client_update_packet(struct bat_priv *bat_priv, struct vis_packet *vis_packet, int vis_info_len); -int vis_init(void); -void vis_quit(void); +int vis_init(struct bat_priv *bat_priv); +void vis_quit(struct bat_priv *bat_priv);
#endif /* _NET_BATMAN_ADV_VIS_H_ */
batman_if has the name of the net_dev as extra string in its own structure, but also holds a reference to the actual net_device structure which always has the current name of the device. This makes it unneccessary and also more complex because we must update the name in situations when we receive a NETDEV_CHANGENAME event.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/hard-interface.c | 29 +++++++++----------------- drivers/staging/batman-adv/originator.c | 8 +++--- drivers/staging/batman-adv/routing.c | 9 ++++--- drivers/staging/batman-adv/send.c | 9 ++++--- drivers/staging/batman-adv/types.h | 1 - 5 files changed, 24 insertions(+), 32 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 6b8ec28..a58a89a 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -158,7 +158,7 @@ static void check_known_mac_addr(uint8_t *addr) continue;
pr_warning("The newly added mac address (%pM) already exists " - "on: %s\n", addr, batman_if->dev); + "on: %s\n", addr, batman_if->net_dev->name); pr_warning("It is strongly recommended to keep mac addresses " "unique to avoid problems!\n"); } @@ -223,7 +223,7 @@ static void hardif_activate_interface(struct batman_if *batman_if) set_primary_if(bat_priv, batman_if);
bat_info(batman_if->soft_iface, "Interface activated: %s\n", - batman_if->dev); + batman_if->net_dev->name);
update_min_mtu(batman_if->soft_iface); return; @@ -238,7 +238,7 @@ static void hardif_deactivate_interface(struct batman_if *batman_if) batman_if->if_status = IF_INACTIVE;
bat_info(batman_if->soft_iface, "Interface deactivated: %s\n", - batman_if->dev); + batman_if->net_dev->name);
update_min_mtu(batman_if->soft_iface); } @@ -269,7 +269,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
if (!batman_if->packet_buff) { bat_err(batman_if->soft_iface, "Can't add interface packet " - "(%s): out of memory\n", batman_if->dev); + "(%s): out of memory\n", batman_if->net_dev->name); goto err; }
@@ -294,7 +294,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->frag_seqno, 1); bat_info(batman_if->soft_iface, "Adding interface: %s\n", - batman_if->dev); + batman_if->net_dev->name);
if (atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < ETH_DATA_LEN + BAT_HEADER_LEN) @@ -304,7 +304,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) "over this interface will be fragmented on layer2 " "which could impact the performance. Setting the MTU " "to %zi would solve the problem.\n", - batman_if->dev, batman_if->net_dev->mtu, + batman_if->net_dev->name, batman_if->net_dev->mtu, ETH_DATA_LEN + BAT_HEADER_LEN);
if (!atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < @@ -314,7 +314,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) "the transport of batman-adv packets. If you experience" " problems getting traffic through try increasing the " "MTU to %zi.\n", - batman_if->dev, batman_if->net_dev->mtu, + batman_if->net_dev->name, batman_if->net_dev->mtu, ETH_DATA_LEN + BAT_HEADER_LEN);
if (hardif_is_iface_up(batman_if)) @@ -322,7 +322,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) else bat_err(batman_if->soft_iface, "Not using interface %s " "(retrying later): interface not active\n", - batman_if->dev); + batman_if->net_dev->name);
/* begin scheduling originator messages on that interface */ schedule_own_packet(batman_if); @@ -345,7 +345,7 @@ void hardif_disable_interface(struct batman_if *batman_if) return;
bat_info(batman_if->soft_iface, "Removing interface: %s\n", - batman_if->dev); + batman_if->net_dev->name); dev_remove_pack(&batman_if->batman_adv_ptype);
bat_priv->num_ifaces--; @@ -389,13 +389,9 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) goto release_dev; }
- batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); - if (!batman_if->dev) - goto free_if; - ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev); if (ret) - goto free_dev; + goto free_if;
batman_if->if_num = -1; batman_if->net_dev = net_dev; @@ -407,8 +403,6 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) list_add_tail_rcu(&batman_if->list, &if_list); return batman_if;
-free_dev: - kfree(batman_if->dev); free_if: kfree(batman_if); release_dev: @@ -421,7 +415,6 @@ static void hardif_free_interface(struct rcu_head *rcu) { struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu);
- kfree(batman_if->dev); kfree(batman_if); }
@@ -476,8 +469,6 @@ static int hard_if_event(struct notifier_block *this, case NETDEV_UNREGISTER: hardif_remove_interface(batman_if); break; - case NETDEV_CHANGENAME: - break; case NETDEV_CHANGEADDR: if (batman_if->if_status == IF_NOT_IN_USE) goto out; diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index d20721b..f25d7fd 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -214,7 +214,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv, "neighbor purge: originator %pM, " "neighbor: %pM, iface: %s\n", orig_node->orig, neigh_node->addr, - neigh_node->if_incoming->dev); + neigh_node->if_incoming->net_dev->name); else bat_dbg(DBG_BATMAN, bat_priv, "neighbor timeout: originator %pM, " @@ -332,8 +332,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) rcu_read_lock(); seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->dev, bat_priv->primary_if->addr_str, - net_dev->name); + bat_priv->primary_if->net_dev->name, + bat_priv->primary_if->addr_str, net_dev->name); seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops"); @@ -361,7 +361,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%-17s %4i.%03is (%3i) %17s [%10s]:", orig_str, last_seen_secs, last_seen_msecs, orig_node->router->tq_avg, router_str, - orig_node->router->if_incoming->dev); + orig_node->router->if_incoming->net_dev->name);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { addr_to_string(orig_str, neigh_node->addr); diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 34cc321..eda08b5 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -557,10 +557,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, "Received BATMAN packet via NB: %pM, IF: %s [%s] " "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, " "TTL %d, V %d, IDF %d)\n", - ethhdr->h_source, if_incoming->dev, if_incoming->addr_str, - batman_packet->orig, batman_packet->prev_sender, - batman_packet->seqno, batman_packet->tq, batman_packet->ttl, - batman_packet->version, has_directlink_flag); + ethhdr->h_source, if_incoming->net_dev->name, + if_incoming->addr_str, batman_packet->orig, + batman_packet->prev_sender, batman_packet->seqno, + batman_packet->tq, batman_packet->ttl, batman_packet->version, + has_directlink_flag);
list_for_each_entry_rcu(batman_if, &if_list, list) { if (batman_if->if_status != IF_ACTIVE) diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index e9980ef..5d57ef5 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -68,7 +68,7 @@ int send_skb_packet(struct sk_buff *skb,
if (!(batman_if->net_dev->flags & IFF_UP)) { pr_warning("Interface %s is not up - can't send packet via " - "that interface!\n", batman_if->dev); + "that interface!\n", batman_if->net_dev->name); goto send_skb_err; }
@@ -141,7 +141,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, batman_packet->tq, batman_packet->ttl, (batman_packet->flags & DIRECTLINK ? "on" : "off"), - batman_if->dev, batman_if->addr_str); + batman_if->net_dev->name, batman_if->addr_str);
buff_pos += sizeof(struct batman_packet) + (batman_packet->num_hna * ETH_ALEN); @@ -186,7 +186,8 @@ static void send_packet(struct forw_packet *forw_packet) "on interface %s [%s]\n", (forw_packet->own ? "Sending own" : "Forwarding"), batman_packet->orig, ntohl(batman_packet->seqno), - batman_packet->ttl, forw_packet->if_incoming->dev, + batman_packet->ttl, + forw_packet->if_incoming->net_dev->name, forw_packet->if_incoming->addr_str);
/* skb is only used once and than forw_packet is free'd */ @@ -521,7 +522,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, if (batman_if) bat_dbg(DBG_BATMAN, bat_priv, "purge_outstanding_packets(): %s\n", - batman_if->dev); + batman_if->net_dev->name); else bat_dbg(DBG_BATMAN, bat_priv, "purge_outstanding_packets()\n"); diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index b4f2b0c..e779c4a 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -36,7 +36,6 @@ struct batman_if { struct list_head list; int16_t if_num; - char *dev; char if_status; char addr_str[ETH_STR_LEN]; struct net_device *net_dev;
Information about dropped packets are usually only interesting for debugging purposes and otherwise open the possibility to flood the logs of the target machine with useless information.
pr_debug will not output those information on a nodebug kernel.
Reported-by: Vasiliy Kulikov segooon@gmail.com Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/routing.c | 15 +++++++-------- drivers/staging/batman-adv/vis.c | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index eda08b5..e12fd99 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -859,9 +859,9 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
/* send TTL exceeded if packet is an echo request (traceroute) */ if (icmp_packet->msg_type != ECHO_REQUEST) { - pr_warning("Warning - can't forward icmp packet from %pM to " - "%pM: ttl exceeded\n", icmp_packet->orig, - icmp_packet->dst); + pr_debug("Warning - can't forward icmp packet from %pM to " + "%pM: ttl exceeded\n", icmp_packet->orig, + icmp_packet->dst); return NET_RX_DROP; }
@@ -1141,9 +1141,9 @@ static int route_unicast_packet(struct sk_buff *skb,
/* TTL exceeded */ if (unicast_packet->ttl < 2) { - pr_warning("Warning - can't forward unicast packet from %pM to " - "%pM: ttl exceeded\n", ethhdr->h_source, - unicast_packet->dest); + pr_debug("Warning - can't forward unicast packet from %pM to " + "%pM: ttl exceeded\n", ethhdr->h_source, + unicast_packet->dest); return NET_RX_DROP; }
@@ -1224,8 +1224,7 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) hash_find(bat_priv->orig_hash, unicast_packet->orig));
if (!orig_node) { - pr_warning("couldn't find orig node for " - "fragmentation\n"); + pr_debug("couldn't find orig node for fragmentation\n"); spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); return NET_RX_DROP; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 071d3b7..b2cec8e 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -745,7 +745,7 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
packet = (struct vis_packet *)info->skb_packet->data; if (packet->ttl < 2) { - pr_warning("Error - can't send vis packet: ttl exceeded\n"); + pr_debug("Error - can't send vis packet: ttl exceeded\n"); return; }
We must reduce our own mtu when we reduce the mtu of any device we use to transfer our packets. Otherwise we may accept to large packets which gets dropped by the actual device.
Reported-by: Vasiliy Kulikov segooon@gmail.com Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/hard-interface.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index a58a89a..a587da9 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -469,6 +469,10 @@ static int hard_if_event(struct notifier_block *this, case NETDEV_UNREGISTER: hardif_remove_interface(batman_if); break; + case NETDEV_CHANGEMTU: + if (batman_if->soft_iface) + update_min_mtu(batman_if->soft_iface); + break; case NETDEV_CHANGEADDR: if (batman_if->if_status == IF_NOT_IN_USE) goto out;
On Sun, Sep 05, 2010 at 01:58:17AM +0200, Sven Eckelmann wrote:
Hi,
I hope that the fever-induced dreams are over now. Otherwise I will try to write my mails also as little tales. ;)
Nevertheless, I would like to send some patches for 2.6.37. That is not 100% true. We would also like to see the revert 'Revert: "Staging: batman-adv: Adding netfilter-bridge hooks"' too in 2.6.36. It fixes a bug introduced by the commit we revert here.
Ok, I've applied this to both trees to make everything work properly.
The rest is more or less the usual stuff, but more feature patches this time. All patches we depend on are already part of 2.6.36-rc3.
All queued up now, thanks.
greg k-h
b.a.t.m.a.n@lists.open-mesh.org