aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2010-12-16 17:28:17 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-16 18:20:05 -0500
commit63d5e5a727240b317b0c2fa2abeb32b367aea196 (patch)
tree2ad3bd8296e3cc8704112d8e03395572980e7f80 /drivers/staging
parent45241e50e3e741ee2a148693888b48e90e806de9 (diff)
Staging: batman-adv: Remove batman-adv from staging
batman-adv is now moved to net/batman-adv/ and can be removed from staging. Signed-off-by: Sven Eckelmann <sven@narfation.org> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/batman-adv/Kconfig26
-rw-r--r--drivers/staging/batman-adv/Makefile39
-rw-r--r--drivers/staging/batman-adv/README240
-rw-r--r--drivers/staging/batman-adv/TODO10
-rw-r--r--drivers/staging/batman-adv/aggregation.c273
-rw-r--r--drivers/staging/batman-adv/aggregation.h43
-rw-r--r--drivers/staging/batman-adv/bat_debugfs.c360
-rw-r--r--drivers/staging/batman-adv/bat_debugfs.h33
-rw-r--r--drivers/staging/batman-adv/bat_sysfs.c593
-rw-r--r--drivers/staging/batman-adv/bat_sysfs.h42
-rw-r--r--drivers/staging/batman-adv/bitarray.c201
-rw-r--r--drivers/staging/batman-adv/bitarray.h47
-rw-r--r--drivers/staging/batman-adv/gateway_client.c477
-rw-r--r--drivers/staging/batman-adv/gateway_client.h36
-rw-r--r--drivers/staging/batman-adv/gateway_common.c177
-rw-r--r--drivers/staging/batman-adv/gateway_common.h38
-rw-r--r--drivers/staging/batman-adv/hard-interface.c652
-rw-r--r--drivers/staging/batman-adv/hard-interface.h53
-rw-r--r--drivers/staging/batman-adv/hash.c83
-rw-r--r--drivers/staging/batman-adv/hash.h259
-rw-r--r--drivers/staging/batman-adv/icmp_socket.c357
-rw-r--r--drivers/staging/batman-adv/icmp_socket.h34
-rw-r--r--drivers/staging/batman-adv/main.c187
-rw-r--r--drivers/staging/batman-adv/main.h180
-rw-r--r--drivers/staging/batman-adv/originator.c546
-rw-r--r--drivers/staging/batman-adv/originator.h64
-rw-r--r--drivers/staging/batman-adv/packet.h136
-rw-r--r--drivers/staging/batman-adv/ring_buffer.c52
-rw-r--r--drivers/staging/batman-adv/ring_buffer.h28
-rw-r--r--drivers/staging/batman-adv/routing.c1393
-rw-r--r--drivers/staging/batman-adv/routing.h48
-rw-r--r--drivers/staging/batman-adv/send.c586
-rw-r--r--drivers/staging/batman-adv/send.h41
-rw-r--r--drivers/staging/batman-adv/soft-interface.c697
-rw-r--r--drivers/staging/batman-adv/soft-interface.h35
-rw-r--r--drivers/staging/batman-adv/sysfs-class-net-batman-adv14
-rw-r--r--drivers/staging/batman-adv/sysfs-class-net-mesh69
-rw-r--r--drivers/staging/batman-adv/translation-table.c528
-rw-r--r--drivers/staging/batman-adv/translation-table.h45
-rw-r--r--drivers/staging/batman-adv/types.h271
-rw-r--r--drivers/staging/batman-adv/unicast.c343
-rw-r--r--drivers/staging/batman-adv/unicast.h35
-rw-r--r--drivers/staging/batman-adv/vis.c903
-rw-r--r--drivers/staging/batman-adv/vis.h37
46 files changed, 0 insertions, 10314 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index f2d9fe8cde5f..923e28f83208 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -129,8 +129,6 @@ source "drivers/staging/wlags49_h2/Kconfig"
129 129
130source "drivers/staging/wlags49_h25/Kconfig" 130source "drivers/staging/wlags49_h25/Kconfig"
131 131
132source "drivers/staging/batman-adv/Kconfig"
133
134source "drivers/staging/samsung-laptop/Kconfig" 132source "drivers/staging/samsung-laptop/Kconfig"
135 133
136source "drivers/staging/sm7xx/Kconfig" 134source "drivers/staging/sm7xx/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 10c72bb1940d..4e6797f6444a 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_IIO) += iio/
47obj-$(CONFIG_ZRAM) += zram/ 47obj-$(CONFIG_ZRAM) += zram/
48obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ 48obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
49obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ 49obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
50obj-$(CONFIG_BATMAN_ADV) += batman-adv/
51obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/ 50obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
52obj-$(CONFIG_FB_SM7XX) += sm7xx/ 51obj-$(CONFIG_FB_SM7XX) += sm7xx/
53obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ 52obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
diff --git a/drivers/staging/batman-adv/Kconfig b/drivers/staging/batman-adv/Kconfig
deleted file mode 100644
index 8553f3517454..000000000000
--- a/drivers/staging/batman-adv/Kconfig
+++ /dev/null
@@ -1,26 +0,0 @@
1#
2# B.A.T.M.A.N meshing protocol
3#
4
5config BATMAN_ADV
6 tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
7 depends on NET
8 default n
9 ---help---
10
11 B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
12 a routing protocol for multi-hop ad-hoc mesh networks. The
13 networks may be wired or wireless. See
14 http://www.open-mesh.org/ for more information and user space
15 tools.
16
17config BATMAN_ADV_DEBUG
18 bool "B.A.T.M.A.N. debugging"
19 depends on BATMAN_ADV != n
20 ---help---
21
22 This is an option for use by developers; most people should
23 say N here. This enables compilation of support for
24 outputting debugging information to the kernel log. The
25 output is controlled via the module parameter debug.
26
diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile
deleted file mode 100644
index d936aeccd194..000000000000
--- a/drivers/staging/batman-adv/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
1#
2# Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3#
4# Marek Lindner, Simon Wunderlich
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of version 2 of the GNU General Public
8# License as published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18# 02110-1301, USA
19#
20
21obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
22batman-adv-y += aggregation.o
23batman-adv-y += bat_debugfs.o
24batman-adv-y += bat_sysfs.o
25batman-adv-y += bitarray.o
26batman-adv-y += gateway_client.o
27batman-adv-y += gateway_common.o
28batman-adv-y += hard-interface.o
29batman-adv-y += hash.o
30batman-adv-y += icmp_socket.o
31batman-adv-y += main.o
32batman-adv-y += originator.o
33batman-adv-y += ring_buffer.o
34batman-adv-y += routing.o
35batman-adv-y += send.o
36batman-adv-y += soft-interface.o
37batman-adv-y += translation-table.o
38batman-adv-y += unicast.o
39batman-adv-y += vis.o
diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README
deleted file mode 100644
index 77f0cdd5b0dd..000000000000
--- a/drivers/staging/batman-adv/README
+++ /dev/null
@@ -1,240 +0,0 @@
1[state: 21-11-2010]
2
3BATMAN-ADV
4----------
5
6Batman advanced is a new approach to wireless networking which
7does no longer operate on the IP basis. Unlike the batman daemon,
8which exchanges information using UDP packets and sets routing
9tables, batman-advanced operates on ISO/OSI Layer 2 only and uses
10and routes (or better: bridges) Ethernet Frames. It emulates a
11virtual network switch of all nodes participating. Therefore all
12nodes appear to be link local, thus all higher operating proto-
13cols won't be affected by any changes within the network. You can
14run almost any protocol above batman advanced, prominent examples
15are: IPv4, IPv6, DHCP, IPX.
16
17Batman advanced was implemented as a Linux kernel driver to re-
18duce the overhead to a minimum. It does not depend on any (other)
19network driver, and can be used on wifi as well as ethernet lan,
20vpn, etc ... (anything with ethernet-style layer 2).
21
22CONFIGURATION
23-------------
24
25Load the batman-adv module into your kernel:
26
27# insmod batman-adv.ko
28
29The module is now waiting for activation. You must add some in-
30terfaces on which batman can operate. After loading the module
31batman advanced will scan your systems interfaces to search for
32compatible interfaces. Once found, it will create subfolders in
33the /sys directories of each supported interface, e.g.
34
35# ls /sys/class/net/eth0/batman_adv/
36# iface_status mesh_iface
37
38If an interface does not have the "batman_adv" subfolder it prob-
39ably is not supported. Not supported interfaces are: loopback,
40non-ethernet and batman's own interfaces.
41
42Note: After the module was loaded it will continuously watch for
43new interfaces to verify the compatibility. There is no need to
44reload the module if you plug your USB wifi adapter into your ma-
45chine after batman advanced was initially loaded.
46
47To activate a given interface simply write "bat0" into its
48"mesh_iface" file inside the batman_adv subfolder:
49
50# echo bat0 > /sys/class/net/eth0/batman_adv/mesh_iface
51
52Repeat this step for all interfaces you wish to add. Now batman
53starts using/broadcasting on this/these interface(s).
54
55By reading the "iface_status" file you can check its status:
56
57# cat /sys/class/net/eth0/batman_adv/iface_status
58# active
59
60To deactivate an interface you have to write "none" into its
61"mesh_iface" file:
62
63# echo none > /sys/class/net/eth0/batman_adv/mesh_iface
64
65
66All mesh wide settings can be found in batman's own interface
67folder:
68
69# ls /sys/class/net/bat0/mesh/
70# aggregated_ogms bonding fragmentation orig_interval
71# vis_mode
72
73
74There is a special folder for debugging informations:
75
76# ls /sys/kernel/debug/batman_adv/bat0/
77# originators socket transtable_global transtable_local
78# vis_data
79
80
81Some of the files contain all sort of status information regard-
82ing the mesh network. For example, you can view the table of
83originators (mesh participants) with:
84
85# cat /sys/kernel/debug/batman_adv/bat0/originators
86
87Other files allow to change batman's behaviour to better fit your
88requirements. For instance, you can check the current originator
89interval (value in milliseconds which determines how often batman
90sends its broadcast packets):
91
92# cat /sys/class/net/bat0/mesh/orig_interval
93# 1000
94
95and also change its value:
96
97# echo 3000 > /sys/class/net/bat0/mesh/orig_interval
98
99In very mobile scenarios, you might want to adjust the originator
100interval to a lower value. This will make the mesh more respon-
101sive to topology changes, but will also increase the overhead.
102
103
104USAGE
105-----
106
107To make use of your newly created mesh, batman advanced provides
108a new interface "bat0" which you should use from this point on.
109All interfaces added to batman advanced are not relevant any
110longer because batman handles them for you. Basically, one "hands
111over" the data by using the batman interface and batman will make
112sure it reaches its destination.
113
114The "bat0" interface can be used like any other regular inter-
115face. It needs an IP address which can be either statically con-
116figured or dynamically (by using DHCP or similar services):
117
118# NodeA: ifconfig bat0 192.168.0.1
119# NodeB: ifconfig bat0 192.168.0.2
120# NodeB: ping 192.168.0.1
121
122Note: In order to avoid problems remove all IP addresses previ-
123ously assigned to interfaces now used by batman advanced, e.g.
124
125# ifconfig eth0 0.0.0.0
126
127
128VISUALIZATION
129-------------
130
131If you want topology visualization, at least one mesh node must
132be configured as VIS-server:
133
134# echo "server" > /sys/class/net/bat0/mesh/vis_mode
135
136Each node is either configured as "server" or as "client" (de-
137fault: "client"). Clients send their topology data to the server
138next to them, and server synchronize with other servers. If there
139is no server configured (default) within the mesh, no topology
140information will be transmitted. With these "synchronizing
141servers", there can be 1 or more vis servers sharing the same (or
142at least very similar) data.
143
144When configured as server, you can get a topology snapshot of
145your mesh:
146
147# cat /sys/kernel/debug/batman_adv/bat0/vis_data
148
149This raw output is intended to be easily parsable and convertable
150with other tools. Have a look at the batctl README if you want a
151vis output in dot or json format for instance and how those out-
152puts could then be visualised in an image.
153
154The raw format consists of comma separated values per entry where
155each entry is giving information about a certain source inter-
156face. Each entry can/has to have the following values:
157-> "mac" - mac address of an originator's source interface
158 (each line begins with it)
159-> "TQ mac value" - src mac's link quality towards mac address
160 of a neighbor originator's interface which
161 is being used for routing
162-> "HNA mac" - HNA announced by source mac
163-> "PRIMARY" - this is a primary interface
164-> "SEC mac" - secondary mac address of source
165 (requires preceding PRIMARY)
166
167The TQ value has a range from 4 to 255 with 255 being the best.
168The HNA entries are showing which hosts are connected to the mesh
169via bat0 or being bridged into the mesh network. The PRIMARY/SEC
170values are only applied on primary interfaces
171
172
173LOGGING/DEBUGGING
174-----------------
175
176All error messages, warnings and information messages are sent to
177the kernel log. Depending on your operating system distribution
178this can be read in one of a number of ways. Try using the com-
179mands: dmesg, logread, or looking in the files /var/log/kern.log
180or /var/log/syslog. All batman-adv messages are prefixed with
181"batman-adv:" So to see just these messages try
182
183# dmesg | grep batman-adv
184
185When investigating problems with your mesh network it is some-
186times necessary to see more detail debug messages. This must be
187enabled when compiling the batman-adv module. When building bat-
188man-adv as part of kernel, use "make menuconfig" and enable the
189option "B.A.T.M.A.N. debugging".
190
191Those additional debug messages can be accessed using a special
192file in debugfs
193
194# cat /sys/kernel/debug/batman_adv/bat0/log
195
196The additional debug output is by default disabled. It can be en-
197abled during run time. Following log_levels are defined:
198
1990 - All debug output disabled
2001 - Enable messages related to routing / flooding / broadcasting
2012 - Enable route or hna added / changed / deleted
2023 - Enable all messages
203
204The debug output can be changed at runtime using the file
205/sys/class/net/bat0/mesh/log_level. e.g.
206
207# echo 2 > /sys/class/net/bat0/mesh/log_level
208
209will enable debug messages for when routes or HNAs change.
210
211
212BATCTL
213------
214
215As batman advanced operates on layer 2 all hosts participating in
216the virtual switch are completely transparent for all protocols
217above layer 2. Therefore the common diagnosis tools do not work
218as expected. To overcome these problems batctl was created. At
219the moment the batctl contains ping, traceroute, tcpdump and
220interfaces to the kernel module settings.
221
222For more information, please see the manpage (man batctl).
223
224batctl is available on http://www.open-mesh.org/
225
226
227CONTACT
228-------
229
230Please send us comments, experiences, questions, anything :)
231
232IRC: #batman on irc.freenode.org
233Mailing-list: b.a.t.m.a.n@b.a.t.m.a.n@lists.open-mesh.org
234 (optional subscription at
235 https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
236
237You can also contact the Authors:
238
239Marek Lindner <lindner_marek@yahoo.de>
240Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO
deleted file mode 100644
index ba69ba3ab62d..000000000000
--- a/drivers/staging/batman-adv/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
1 * Request a new review
2 * Process the comments from the review
3 * Move into mainline proper
4
5Please send all patches to:
6 Marek Lindner <lindner_marek@yahoo.de>
7 Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
8 Sven Eckelmann <sven.eckelmann@gmx.de>
9 b.a.t.m.a.n@lists.open-mesh.org
10 Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c
deleted file mode 100644
index 0c92e3b35abf..000000000000
--- a/drivers/staging/batman-adv/aggregation.c
+++ /dev/null
@@ -1,273 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "aggregation.h"
24#include "send.h"
25#include "routing.h"
26
27/* calculate the size of the hna information for a given packet */
28static int hna_len(struct batman_packet *batman_packet)
29{
30 return batman_packet->num_hna * ETH_ALEN;
31}
32
33/* return true if new_packet can be aggregated with forw_packet */
34static bool can_aggregate_with(struct batman_packet *new_batman_packet,
35 int packet_len,
36 unsigned long send_time,
37 bool directlink,
38 struct batman_if *if_incoming,
39 struct forw_packet *forw_packet)
40{
41 struct batman_packet *batman_packet =
42 (struct batman_packet *)forw_packet->skb->data;
43 int aggregated_bytes = forw_packet->packet_len + packet_len;
44
45 /**
46 * we can aggregate the current packet to this aggregated packet
47 * if:
48 *
49 * - the send time is within our MAX_AGGREGATION_MS time
50 * - the resulting packet wont be bigger than
51 * MAX_AGGREGATION_BYTES
52 */
53
54 if (time_before(send_time, forw_packet->send_time) &&
55 time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
56 forw_packet->send_time) &&
57 (aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
58
59 /**
60 * check aggregation compatibility
61 * -> direct link packets are broadcasted on
62 * their interface only
63 * -> aggregate packet if the current packet is
64 * a "global" packet as well as the base
65 * packet
66 */
67
68 /* packets without direct link flag and high TTL
69 * are flooded through the net */
70 if ((!directlink) &&
71 (!(batman_packet->flags & DIRECTLINK)) &&
72 (batman_packet->ttl != 1) &&
73
74 /* own packets originating non-primary
75 * interfaces leave only that interface */
76 ((!forw_packet->own) ||
77 (forw_packet->if_incoming->if_num == 0)))
78 return true;
79
80 /* if the incoming packet is sent via this one
81 * interface only - we still can aggregate */
82 if ((directlink) &&
83 (new_batman_packet->ttl == 1) &&
84 (forw_packet->if_incoming == if_incoming) &&
85
86 /* packets from direct neighbors or
87 * own secondary interface packets
88 * (= secondary interface packets in general) */
89 (batman_packet->flags & DIRECTLINK ||
90 (forw_packet->own &&
91 forw_packet->if_incoming->if_num != 0)))
92 return true;
93 }
94
95 return false;
96}
97
98#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
99/* create a new aggregated packet and add this packet to it */
100static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
101 unsigned long send_time, bool direct_link,
102 struct batman_if *if_incoming,
103 int own_packet)
104{
105 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
106 struct forw_packet *forw_packet_aggr;
107 unsigned char *skb_buff;
108
109 /* own packet should always be scheduled */
110 if (!own_packet) {
111 if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
112 bat_dbg(DBG_BATMAN, bat_priv,
113 "batman packet queue full\n");
114 return;
115 }
116 }
117
118 forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
119 if (!forw_packet_aggr) {
120 if (!own_packet)
121 atomic_inc(&bat_priv->batman_queue_left);
122 return;
123 }
124
125 if ((atomic_read(&bat_priv->aggregated_ogms)) &&
126 (packet_len < MAX_AGGREGATION_BYTES))
127 forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES +
128 sizeof(struct ethhdr));
129 else
130 forw_packet_aggr->skb = dev_alloc_skb(packet_len +
131 sizeof(struct ethhdr));
132
133 if (!forw_packet_aggr->skb) {
134 if (!own_packet)
135 atomic_inc(&bat_priv->batman_queue_left);
136 kfree(forw_packet_aggr);
137 return;
138 }
139 skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
140
141 INIT_HLIST_NODE(&forw_packet_aggr->list);
142
143 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
144 forw_packet_aggr->packet_len = packet_len;
145 memcpy(skb_buff, packet_buff, packet_len);
146
147 forw_packet_aggr->own = own_packet;
148 forw_packet_aggr->if_incoming = if_incoming;
149 forw_packet_aggr->num_packets = 0;
150 forw_packet_aggr->direct_link_flags = 0;
151 forw_packet_aggr->send_time = send_time;
152
153 /* save packet direct link flag status */
154 if (direct_link)
155 forw_packet_aggr->direct_link_flags |= 1;
156
157 /* add new packet to packet list */
158 spin_lock_bh(&bat_priv->forw_bat_list_lock);
159 hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
160 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
161
162 /* start timer for this packet */
163 INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
164 send_outstanding_bat_packet);
165 queue_delayed_work(bat_event_workqueue,
166 &forw_packet_aggr->delayed_work,
167 send_time - jiffies);
168}
169
170/* aggregate a new packet into the existing aggregation */
171static void aggregate(struct forw_packet *forw_packet_aggr,
172 unsigned char *packet_buff,
173 int packet_len,
174 bool direct_link)
175{
176 unsigned char *skb_buff;
177
178 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
179 memcpy(skb_buff, packet_buff, packet_len);
180 forw_packet_aggr->packet_len += packet_len;
181 forw_packet_aggr->num_packets++;
182
183 /* save packet direct link flag status */
184 if (direct_link)
185 forw_packet_aggr->direct_link_flags |=
186 (1 << forw_packet_aggr->num_packets);
187}
188
189void add_bat_packet_to_list(struct bat_priv *bat_priv,
190 unsigned char *packet_buff, int packet_len,
191 struct batman_if *if_incoming, char own_packet,
192 unsigned long send_time)
193{
194 /**
195 * _aggr -> pointer to the packet we want to aggregate with
196 * _pos -> pointer to the position in the queue
197 */
198 struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL;
199 struct hlist_node *tmp_node;
200 struct batman_packet *batman_packet =
201 (struct batman_packet *)packet_buff;
202 bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0;
203
204 /* find position for the packet in the forward queue */
205 spin_lock_bh(&bat_priv->forw_bat_list_lock);
206 /* own packets are not to be aggregated */
207 if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) {
208 hlist_for_each_entry(forw_packet_pos, tmp_node,
209 &bat_priv->forw_bat_list, list) {
210 if (can_aggregate_with(batman_packet,
211 packet_len,
212 send_time,
213 direct_link,
214 if_incoming,
215 forw_packet_pos)) {
216 forw_packet_aggr = forw_packet_pos;
217 break;
218 }
219 }
220 }
221
222 /* nothing to aggregate with - either aggregation disabled or no
223 * suitable aggregation packet found */
224 if (forw_packet_aggr == NULL) {
225 /* the following section can run without the lock */
226 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
227
228 /**
229 * if we could not aggregate this packet with one of the others
230 * we hold it back for a while, so that it might be aggregated
231 * later on
232 */
233 if ((!own_packet) &&
234 (atomic_read(&bat_priv->aggregated_ogms)))
235 send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
236
237 new_aggregated_packet(packet_buff, packet_len,
238 send_time, direct_link,
239 if_incoming, own_packet);
240 } else {
241 aggregate(forw_packet_aggr,
242 packet_buff, packet_len,
243 direct_link);
244 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
245 }
246}
247
248/* unpack the aggregated packets and process them one by one */
249void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
250 int packet_len, struct batman_if *if_incoming)
251{
252 struct batman_packet *batman_packet;
253 int buff_pos = 0;
254 unsigned char *hna_buff;
255
256 batman_packet = (struct batman_packet *)packet_buff;
257
258 do {
259 /* network to host order for our 32bit seqno, and the
260 orig_interval. */
261 batman_packet->seqno = ntohl(batman_packet->seqno);
262
263 hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
264 receive_bat_packet(ethhdr, batman_packet,
265 hna_buff, hna_len(batman_packet),
266 if_incoming);
267
268 buff_pos += BAT_PACKET_LEN + hna_len(batman_packet);
269 batman_packet = (struct batman_packet *)
270 (packet_buff + buff_pos);
271 } while (aggregated_packet(buff_pos, packet_len,
272 batman_packet->num_hna));
273}
diff --git a/drivers/staging/batman-adv/aggregation.h b/drivers/staging/batman-adv/aggregation.h
deleted file mode 100644
index 71a91b3da913..000000000000
--- a/drivers/staging/batman-adv/aggregation.h
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_AGGREGATION_H_
23#define _NET_BATMAN_ADV_AGGREGATION_H_
24
25#include "main.h"
26
27/* is there another aggregated packet here? */
28static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna)
29{
30 int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN);
31
32 return (next_buff_pos <= packet_len) &&
33 (next_buff_pos <= MAX_AGGREGATION_BYTES);
34}
35
36void add_bat_packet_to_list(struct bat_priv *bat_priv,
37 unsigned char *packet_buff, int packet_len,
38 struct batman_if *if_incoming, char own_packet,
39 unsigned long send_time);
40void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
41 int packet_len, struct batman_if *if_incoming);
42
43#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/drivers/staging/batman-adv/bat_debugfs.c b/drivers/staging/batman-adv/bat_debugfs.c
deleted file mode 100644
index 0ae81d07f102..000000000000
--- a/drivers/staging/batman-adv/bat_debugfs.c
+++ /dev/null
@@ -1,360 +0,0 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23
24#include <linux/debugfs.h>
25
26#include "bat_debugfs.h"
27#include "translation-table.h"
28#include "originator.h"
29#include "hard-interface.h"
30#include "gateway_common.h"
31#include "gateway_client.h"
32#include "soft-interface.h"
33#include "vis.h"
34#include "icmp_socket.h"
35
36static struct dentry *bat_debugfs;
37
38#ifdef CONFIG_BATMAN_ADV_DEBUG
39#define LOG_BUFF_MASK (log_buff_len-1)
40#define LOG_BUFF(idx) (debug_log->log_buff[(idx) & LOG_BUFF_MASK])
41
42static int log_buff_len = LOG_BUF_LEN;
43
44static void emit_log_char(struct debug_log *debug_log, char c)
45{
46 LOG_BUFF(debug_log->log_end) = c;
47 debug_log->log_end++;
48
49 if (debug_log->log_end - debug_log->log_start > log_buff_len)
50 debug_log->log_start = debug_log->log_end - log_buff_len;
51}
52
53static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
54{
55 int printed_len;
56 va_list args;
57 static char debug_log_buf[256];
58 char *p;
59
60 if (!debug_log)
61 return 0;
62
63 spin_lock_bh(&debug_log->lock);
64 va_start(args, fmt);
65 printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf),
66 fmt, args);
67 va_end(args);
68
69 for (p = debug_log_buf; *p != 0; p++)
70 emit_log_char(debug_log, *p);
71
72 spin_unlock_bh(&debug_log->lock);
73
74 wake_up(&debug_log->queue_wait);
75
76 return 0;
77}
78
79int debug_log(struct bat_priv *bat_priv, char *fmt, ...)
80{
81 va_list args;
82 char tmp_log_buf[256];
83
84 va_start(args, fmt);
85 vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
86 fdebug_log(bat_priv->debug_log, "[%10u] %s",
87 (jiffies / HZ), tmp_log_buf);
88 va_end(args);
89
90 return 0;
91}
92
93static int log_open(struct inode *inode, struct file *file)
94{
95 nonseekable_open(inode, file);
96 file->private_data = inode->i_private;
97 inc_module_count();
98 return 0;
99}
100
101static int log_release(struct inode *inode, struct file *file)
102{
103 dec_module_count();
104 return 0;
105}
106
107static ssize_t log_read(struct file *file, char __user *buf,
108 size_t count, loff_t *ppos)
109{
110 struct bat_priv *bat_priv = file->private_data;
111 struct debug_log *debug_log = bat_priv->debug_log;
112 int error, i = 0;
113 char c;
114
115 if ((file->f_flags & O_NONBLOCK) &&
116 !(debug_log->log_end - debug_log->log_start))
117 return -EAGAIN;
118
119 if ((!buf) || (count < 0))
120 return -EINVAL;
121
122 if (count == 0)
123 return 0;
124
125 if (!access_ok(VERIFY_WRITE, buf, count))
126 return -EFAULT;
127
128 error = wait_event_interruptible(debug_log->queue_wait,
129 (debug_log->log_start - debug_log->log_end));
130
131 if (error)
132 return error;
133
134 spin_lock_bh(&debug_log->lock);
135
136 while ((!error) && (i < count) &&
137 (debug_log->log_start != debug_log->log_end)) {
138 c = LOG_BUFF(debug_log->log_start);
139
140 debug_log->log_start++;
141
142 spin_unlock_bh(&debug_log->lock);
143
144 error = __put_user(c, buf);
145
146 spin_lock_bh(&debug_log->lock);
147
148 buf++;
149 i++;
150
151 }
152
153 spin_unlock_bh(&debug_log->lock);
154
155 if (!error)
156 return i;
157
158 return error;
159}
160
161static unsigned int log_poll(struct file *file, poll_table *wait)
162{
163 struct bat_priv *bat_priv = file->private_data;
164 struct debug_log *debug_log = bat_priv->debug_log;
165
166 poll_wait(file, &debug_log->queue_wait, wait);
167
168 if (debug_log->log_end - debug_log->log_start)
169 return POLLIN | POLLRDNORM;
170
171 return 0;
172}
173
174static const struct file_operations log_fops = {
175 .open = log_open,
176 .release = log_release,
177 .read = log_read,
178 .poll = log_poll,
179 .llseek = no_llseek,
180};
181
182static int debug_log_setup(struct bat_priv *bat_priv)
183{
184 struct dentry *d;
185
186 if (!bat_priv->debug_dir)
187 goto err;
188
189 bat_priv->debug_log = kzalloc(sizeof(struct debug_log), GFP_ATOMIC);
190 if (!bat_priv->debug_log)
191 goto err;
192
193 spin_lock_init(&bat_priv->debug_log->lock);
194 init_waitqueue_head(&bat_priv->debug_log->queue_wait);
195
196 d = debugfs_create_file("log", S_IFREG | S_IRUSR,
197 bat_priv->debug_dir, bat_priv, &log_fops);
198 if (d)
199 goto err;
200
201 return 0;
202
203err:
204 return 1;
205}
206
207static void debug_log_cleanup(struct bat_priv *bat_priv)
208{
209 kfree(bat_priv->debug_log);
210 bat_priv->debug_log = NULL;
211}
212#else /* CONFIG_BATMAN_ADV_DEBUG */
213static int debug_log_setup(struct bat_priv *bat_priv)
214{
215 bat_priv->debug_log = NULL;
216 return 0;
217}
218
219static void debug_log_cleanup(struct bat_priv *bat_priv)
220{
221 return;
222}
223#endif
224
225static int originators_open(struct inode *inode, struct file *file)
226{
227 struct net_device *net_dev = (struct net_device *)inode->i_private;
228 return single_open(file, orig_seq_print_text, net_dev);
229}
230
231static int gateways_open(struct inode *inode, struct file *file)
232{
233 struct net_device *net_dev = (struct net_device *)inode->i_private;
234 return single_open(file, gw_client_seq_print_text, net_dev);
235}
236
237static int softif_neigh_open(struct inode *inode, struct file *file)
238{
239 struct net_device *net_dev = (struct net_device *)inode->i_private;
240 return single_open(file, softif_neigh_seq_print_text, net_dev);
241}
242
243static int transtable_global_open(struct inode *inode, struct file *file)
244{
245 struct net_device *net_dev = (struct net_device *)inode->i_private;
246 return single_open(file, hna_global_seq_print_text, net_dev);
247}
248
249static int transtable_local_open(struct inode *inode, struct file *file)
250{
251 struct net_device *net_dev = (struct net_device *)inode->i_private;
252 return single_open(file, hna_local_seq_print_text, net_dev);
253}
254
255static int vis_data_open(struct inode *inode, struct file *file)
256{
257 struct net_device *net_dev = (struct net_device *)inode->i_private;
258 return single_open(file, vis_seq_print_text, net_dev);
259}
260
261struct bat_debuginfo {
262 struct attribute attr;
263 const struct file_operations fops;
264};
265
266#define BAT_DEBUGINFO(_name, _mode, _open) \
267struct bat_debuginfo bat_debuginfo_##_name = { \
268 .attr = { .name = __stringify(_name), \
269 .mode = _mode, }, \
270 .fops = { .owner = THIS_MODULE, \
271 .open = _open, \
272 .read = seq_read, \
273 .llseek = seq_lseek, \
274 .release = single_release, \
275 } \
276};
277
278static BAT_DEBUGINFO(originators, S_IRUGO, originators_open);
279static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open);
280static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open);
281static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open);
282static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open);
283static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open);
284
285static struct bat_debuginfo *mesh_debuginfos[] = {
286 &bat_debuginfo_originators,
287 &bat_debuginfo_gateways,
288 &bat_debuginfo_softif_neigh,
289 &bat_debuginfo_transtable_global,
290 &bat_debuginfo_transtable_local,
291 &bat_debuginfo_vis_data,
292 NULL,
293};
294
295void debugfs_init(void)
296{
297 bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL);
298 if (bat_debugfs == ERR_PTR(-ENODEV))
299 bat_debugfs = NULL;
300}
301
302void debugfs_destroy(void)
303{
304 if (bat_debugfs) {
305 debugfs_remove_recursive(bat_debugfs);
306 bat_debugfs = NULL;
307 }
308}
309
310int debugfs_add_meshif(struct net_device *dev)
311{
312 struct bat_priv *bat_priv = netdev_priv(dev);
313 struct bat_debuginfo **bat_debug;
314 struct dentry *file;
315
316 if (!bat_debugfs)
317 goto out;
318
319 bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs);
320 if (!bat_priv->debug_dir)
321 goto out;
322
323 bat_socket_setup(bat_priv);
324 debug_log_setup(bat_priv);
325
326 for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) {
327 file = debugfs_create_file(((*bat_debug)->attr).name,
328 S_IFREG | ((*bat_debug)->attr).mode,
329 bat_priv->debug_dir,
330 dev, &(*bat_debug)->fops);
331 if (!file) {
332 bat_err(dev, "Can't add debugfs file: %s/%s\n",
333 dev->name, ((*bat_debug)->attr).name);
334 goto rem_attr;
335 }
336 }
337
338 return 0;
339rem_attr:
340 debugfs_remove_recursive(bat_priv->debug_dir);
341 bat_priv->debug_dir = NULL;
342out:
343#ifdef CONFIG_DEBUG_FS
344 return -ENOMEM;
345#else
346 return 0;
347#endif /* CONFIG_DEBUG_FS */
348}
349
350void debugfs_del_meshif(struct net_device *dev)
351{
352 struct bat_priv *bat_priv = netdev_priv(dev);
353
354 debug_log_cleanup(bat_priv);
355
356 if (bat_debugfs) {
357 debugfs_remove_recursive(bat_priv->debug_dir);
358 bat_priv->debug_dir = NULL;
359 }
360}
diff --git a/drivers/staging/batman-adv/bat_debugfs.h b/drivers/staging/batman-adv/bat_debugfs.h
deleted file mode 100644
index 72df532b7d5f..000000000000
--- a/drivers/staging/batman-adv/bat_debugfs.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22
23#ifndef _NET_BATMAN_ADV_DEBUGFS_H_
24#define _NET_BATMAN_ADV_DEBUGFS_H_
25
26#define DEBUGFS_BAT_SUBDIR "batman_adv"
27
28void debugfs_init(void);
29void debugfs_destroy(void);
30int debugfs_add_meshif(struct net_device *dev);
31void debugfs_del_meshif(struct net_device *dev);
32
33#endif /* _NET_BATMAN_ADV_DEBUGFS_H_ */
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c
deleted file mode 100644
index cd7bb51825f1..000000000000
--- a/drivers/staging/batman-adv/bat_sysfs.c
+++ /dev/null
@@ -1,593 +0,0 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "bat_sysfs.h"
24#include "translation-table.h"
25#include "originator.h"
26#include "hard-interface.h"
27#include "gateway_common.h"
28#include "gateway_client.h"
29#include "vis.h"
30
31#define to_dev(obj) container_of(obj, struct device, kobj)
32#define kobj_to_netdev(obj) to_net_dev(to_dev(obj->parent))
33#define kobj_to_batpriv(obj) netdev_priv(kobj_to_netdev(obj))
34
35/* Use this, if you have customized show and store functions */
36#define BAT_ATTR(_name, _mode, _show, _store) \
37struct bat_attribute bat_attr_##_name = { \
38 .attr = {.name = __stringify(_name), \
39 .mode = _mode }, \
40 .show = _show, \
41 .store = _store, \
42};
43
44#define BAT_ATTR_STORE_BOOL(_name, _post_func) \
45ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
46 char *buff, size_t count) \
47{ \
48 struct net_device *net_dev = kobj_to_netdev(kobj); \
49 struct bat_priv *bat_priv = netdev_priv(net_dev); \
50 return __store_bool_attr(buff, count, _post_func, attr, \
51 &bat_priv->_name, net_dev); \
52}
53
54#define BAT_ATTR_SHOW_BOOL(_name) \
55ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
56 char *buff) \
57{ \
58 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
59 return sprintf(buff, "%s\n", \
60 atomic_read(&bat_priv->_name) == 0 ? \
61 "disabled" : "enabled"); \
62} \
63
64/* Use this, if you are going to turn a [name] in bat_priv on or off */
65#define BAT_ATTR_BOOL(_name, _mode, _post_func) \
66 static BAT_ATTR_STORE_BOOL(_name, _post_func) \
67 static BAT_ATTR_SHOW_BOOL(_name) \
68 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
69
70
71#define BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \
72ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
73 char *buff, size_t count) \
74{ \
75 struct net_device *net_dev = kobj_to_netdev(kobj); \
76 struct bat_priv *bat_priv = netdev_priv(net_dev); \
77 return __store_uint_attr(buff, count, _min, _max, _post_func, \
78 attr, &bat_priv->_name, net_dev); \
79}
80
81#define BAT_ATTR_SHOW_UINT(_name) \
82ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
83 char *buff) \
84{ \
85 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \
86 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name)); \
87} \
88
89/* Use this, if you are going to set [name] in bat_priv to unsigned integer
90 * values only */
91#define BAT_ATTR_UINT(_name, _mode, _min, _max, _post_func) \
92 static BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \
93 static BAT_ATTR_SHOW_UINT(_name) \
94 static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
95
96
97static int store_bool_attr(char *buff, size_t count,
98 struct net_device *net_dev,
99 char *attr_name, atomic_t *attr)
100{
101 int enabled = -1;
102
103 if (buff[count - 1] == '\n')
104 buff[count - 1] = '\0';
105
106 if ((strncmp(buff, "1", 2) == 0) ||
107 (strncmp(buff, "enable", 7) == 0) ||
108 (strncmp(buff, "enabled", 8) == 0))
109 enabled = 1;
110
111 if ((strncmp(buff, "0", 2) == 0) ||
112 (strncmp(buff, "disable", 8) == 0) ||
113 (strncmp(buff, "disabled", 9) == 0))
114 enabled = 0;
115
116 if (enabled < 0) {
117 bat_info(net_dev,
118 "%s: Invalid parameter received: %s\n",
119 attr_name, buff);
120 return -EINVAL;
121 }
122
123 if (atomic_read(attr) == enabled)
124 return count;
125
126 bat_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
127 atomic_read(attr) == 1 ? "enabled" : "disabled",
128 enabled == 1 ? "enabled" : "disabled");
129
130 atomic_set(attr, (unsigned)enabled);
131 return count;
132}
133
134static inline ssize_t __store_bool_attr(char *buff, size_t count,
135 void (*post_func)(struct net_device *),
136 struct attribute *attr,
137 atomic_t *attr_store, struct net_device *net_dev)
138{
139 int ret;
140
141 ret = store_bool_attr(buff, count, net_dev, (char *)attr->name,
142 attr_store);
143 if (post_func && ret)
144 post_func(net_dev);
145
146 return ret;
147}
148
149static int store_uint_attr(char *buff, size_t count,
150 struct net_device *net_dev, char *attr_name,
151 unsigned int min, unsigned int max, atomic_t *attr)
152{
153 unsigned long uint_val;
154 int ret;
155
156 ret = strict_strtoul(buff, 10, &uint_val);
157 if (ret) {
158 bat_info(net_dev,
159 "%s: Invalid parameter received: %s\n",
160 attr_name, buff);
161 return -EINVAL;
162 }
163
164 if (uint_val < min) {
165 bat_info(net_dev, "%s: Value is too small: %lu min: %u\n",
166 attr_name, uint_val, min);
167 return -EINVAL;
168 }
169
170 if (uint_val > max) {
171 bat_info(net_dev, "%s: Value is too big: %lu max: %u\n",
172 attr_name, uint_val, max);
173 return -EINVAL;
174 }
175
176 if (atomic_read(attr) == uint_val)
177 return count;
178
179 bat_info(net_dev, "%s: Changing from: %i to: %lu\n",
180 attr_name, atomic_read(attr), uint_val);
181
182 atomic_set(attr, uint_val);
183 return count;
184}
185
186static inline ssize_t __store_uint_attr(char *buff, size_t count,
187 int min, int max,
188 void (*post_func)(struct net_device *),
189 struct attribute *attr,
190 atomic_t *attr_store, struct net_device *net_dev)
191{
192 int ret;
193
194 ret = store_uint_attr(buff, count, net_dev, (char *)attr->name,
195 min, max, attr_store);
196 if (post_func && ret)
197 post_func(net_dev);
198
199 return ret;
200}
201
202static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
203 char *buff)
204{
205 struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
206 int vis_mode = atomic_read(&bat_priv->vis_mode);
207
208 return sprintf(buff, "%s\n",
209 vis_mode == VIS_TYPE_CLIENT_UPDATE ?
210 "client" : "server");
211}
212
213static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
214 char *buff, size_t count)
215{
216 struct net_device *net_dev = kobj_to_netdev(kobj);
217 struct bat_priv *bat_priv = netdev_priv(net_dev);
218 unsigned long val;
219 int ret, vis_mode_tmp = -1;
220
221 ret = strict_strtoul(buff, 10, &val);
222
223 if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
224 (strncmp(buff, "client", 6) == 0) ||
225 (strncmp(buff, "off", 3) == 0))
226 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
227
228 if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
229 (strncmp(buff, "server", 6) == 0))
230 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
231
232 if (vis_mode_tmp < 0) {
233 if (buff[count - 1] == '\n')
234 buff[count - 1] = '\0';
235
236 bat_info(net_dev,
237 "Invalid parameter for 'vis mode' setting received: "
238 "%s\n", buff);
239 return -EINVAL;
240 }
241
242 if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
243 return count;
244
245 bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
246 atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
247 "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
248 "client" : "server");
249
250 atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
251 return count;
252}
253
254static void post_gw_deselect(struct net_device *net_dev)
255{
256 struct bat_priv *bat_priv = netdev_priv(net_dev);
257 gw_deselect(bat_priv);
258}
259
260static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr,
261 char *buff)
262{
263 struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
264 int bytes_written;
265
266 switch (atomic_read(&bat_priv->gw_mode)) {
267 case GW_MODE_CLIENT:
268 bytes_written = sprintf(buff, "%s\n", GW_MODE_CLIENT_NAME);
269 break;
270 case GW_MODE_SERVER:
271 bytes_written = sprintf(buff, "%s\n", GW_MODE_SERVER_NAME);
272 break;
273 default:
274 bytes_written = sprintf(buff, "%s\n", GW_MODE_OFF_NAME);
275 break;
276 }
277
278 return bytes_written;
279}
280
281static ssize_t store_gw_mode(struct kobject *kobj, struct attribute *attr,
282 char *buff, size_t count)
283{
284 struct net_device *net_dev = kobj_to_netdev(kobj);
285 struct bat_priv *bat_priv = netdev_priv(net_dev);
286 char *curr_gw_mode_str;
287 int gw_mode_tmp = -1;
288
289 if (buff[count - 1] == '\n')
290 buff[count - 1] = '\0';
291
292 if (strncmp(buff, GW_MODE_OFF_NAME, strlen(GW_MODE_OFF_NAME)) == 0)
293 gw_mode_tmp = GW_MODE_OFF;
294
295 if (strncmp(buff, GW_MODE_CLIENT_NAME,
296 strlen(GW_MODE_CLIENT_NAME)) == 0)
297 gw_mode_tmp = GW_MODE_CLIENT;
298
299 if (strncmp(buff, GW_MODE_SERVER_NAME,
300 strlen(GW_MODE_SERVER_NAME)) == 0)
301 gw_mode_tmp = GW_MODE_SERVER;
302
303 if (gw_mode_tmp < 0) {
304 bat_info(net_dev,
305 "Invalid parameter for 'gw mode' setting received: "
306 "%s\n", buff);
307 return -EINVAL;
308 }
309
310 if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
311 return count;
312
313 switch (atomic_read(&bat_priv->gw_mode)) {
314 case GW_MODE_CLIENT:
315 curr_gw_mode_str = GW_MODE_CLIENT_NAME;
316 break;
317 case GW_MODE_SERVER:
318 curr_gw_mode_str = GW_MODE_SERVER_NAME;
319 break;
320 default:
321 curr_gw_mode_str = GW_MODE_OFF_NAME;
322 break;
323 }
324
325 bat_info(net_dev, "Changing gw mode from: %s to: %s\n",
326 curr_gw_mode_str, buff);
327
328 gw_deselect(bat_priv);
329 atomic_set(&bat_priv->gw_mode, (unsigned)gw_mode_tmp);
330 return count;
331}
332
333static ssize_t show_gw_bwidth(struct kobject *kobj, struct attribute *attr,
334 char *buff)
335{
336 struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
337 int down, up;
338 int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth);
339
340 gw_bandwidth_to_kbit(gw_bandwidth, &down, &up);
341 return sprintf(buff, "%i%s/%i%s\n",
342 (down > 2048 ? down / 1024 : down),
343 (down > 2048 ? "MBit" : "KBit"),
344 (up > 2048 ? up / 1024 : up),
345 (up > 2048 ? "MBit" : "KBit"));
346}
347
348static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
349 char *buff, size_t count)
350{
351 struct net_device *net_dev = kobj_to_netdev(kobj);
352
353 if (buff[count - 1] == '\n')
354 buff[count - 1] = '\0';
355
356 return gw_bandwidth_set(net_dev, buff, count);
357}
358
359BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
360BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
361BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
362static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
363static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
364BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
365BAT_ATTR_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL);
366BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
367 post_gw_deselect);
368static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
369 store_gw_bwidth);
370#ifdef CONFIG_BATMAN_ADV_DEBUG
371BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL);
372#endif
373
374static struct bat_attribute *mesh_attrs[] = {
375 &bat_attr_aggregated_ogms,
376 &bat_attr_bonding,
377 &bat_attr_fragmentation,
378 &bat_attr_vis_mode,
379 &bat_attr_gw_mode,
380 &bat_attr_orig_interval,
381 &bat_attr_hop_penalty,
382 &bat_attr_gw_sel_class,
383 &bat_attr_gw_bandwidth,
384#ifdef CONFIG_BATMAN_ADV_DEBUG
385 &bat_attr_log_level,
386#endif
387 NULL,
388};
389
390int sysfs_add_meshif(struct net_device *dev)
391{
392 struct kobject *batif_kobject = &dev->dev.kobj;
393 struct bat_priv *bat_priv = netdev_priv(dev);
394 struct bat_attribute **bat_attr;
395 int err;
396
397 bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
398 batif_kobject);
399 if (!bat_priv->mesh_obj) {
400 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
401 SYSFS_IF_MESH_SUBDIR);
402 goto out;
403 }
404
405 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
406 err = sysfs_create_file(bat_priv->mesh_obj,
407 &((*bat_attr)->attr));
408 if (err) {
409 bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
410 dev->name, SYSFS_IF_MESH_SUBDIR,
411 ((*bat_attr)->attr).name);
412 goto rem_attr;
413 }
414 }
415
416 return 0;
417
418rem_attr:
419 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
420 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
421
422 kobject_put(bat_priv->mesh_obj);
423 bat_priv->mesh_obj = NULL;
424out:
425 return -ENOMEM;
426}
427
428void sysfs_del_meshif(struct net_device *dev)
429{
430 struct bat_priv *bat_priv = netdev_priv(dev);
431 struct bat_attribute **bat_attr;
432
433 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
434 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
435
436 kobject_put(bat_priv->mesh_obj);
437 bat_priv->mesh_obj = NULL;
438}
439
440static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
441 char *buff)
442{
443 struct net_device *net_dev = kobj_to_netdev(kobj);
444 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
445 ssize_t length;
446
447 if (!batman_if)
448 return 0;
449
450 length = sprintf(buff, "%s\n", batman_if->if_status == IF_NOT_IN_USE ?
451 "none" : batman_if->soft_iface->name);
452
453 kref_put(&batman_if->refcount, hardif_free_ref);
454
455 return length;
456}
457
458static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
459 char *buff, size_t count)
460{
461 struct net_device *net_dev = kobj_to_netdev(kobj);
462 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
463 int status_tmp = -1;
464 int ret;
465
466 if (!batman_if)
467 return count;
468
469 if (buff[count - 1] == '\n')
470 buff[count - 1] = '\0';
471
472 if (strlen(buff) >= IFNAMSIZ) {
473 pr_err("Invalid parameter for 'mesh_iface' setting received: "
474 "interface name too long '%s'\n", buff);
475 kref_put(&batman_if->refcount, hardif_free_ref);
476 return -EINVAL;
477 }
478
479 if (strncmp(buff, "none", 4) == 0)
480 status_tmp = IF_NOT_IN_USE;
481 else
482 status_tmp = IF_I_WANT_YOU;
483
484 if ((batman_if->if_status == status_tmp) || ((batman_if->soft_iface) &&
485 (strncmp(batman_if->soft_iface->name, buff, IFNAMSIZ) == 0))) {
486 kref_put(&batman_if->refcount, hardif_free_ref);
487 return count;
488 }
489
490 if (status_tmp == IF_NOT_IN_USE) {
491 rtnl_lock();
492 hardif_disable_interface(batman_if);
493 rtnl_unlock();
494 kref_put(&batman_if->refcount, hardif_free_ref);
495 return count;
496 }
497
498 /* if the interface already is in use */
499 if (batman_if->if_status != IF_NOT_IN_USE) {
500 rtnl_lock();
501 hardif_disable_interface(batman_if);
502 rtnl_unlock();
503 }
504
505 ret = hardif_enable_interface(batman_if, buff);
506 kref_put(&batman_if->refcount, hardif_free_ref);
507
508 return ret;
509}
510
511static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
512 char *buff)
513{
514 struct net_device *net_dev = kobj_to_netdev(kobj);
515 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
516 ssize_t length;
517
518 if (!batman_if)
519 return 0;
520
521 switch (batman_if->if_status) {
522 case IF_TO_BE_REMOVED:
523 length = sprintf(buff, "disabling\n");
524 break;
525 case IF_INACTIVE:
526 length = sprintf(buff, "inactive\n");
527 break;
528 case IF_ACTIVE:
529 length = sprintf(buff, "active\n");
530 break;
531 case IF_TO_BE_ACTIVATED:
532 length = sprintf(buff, "enabling\n");
533 break;
534 case IF_NOT_IN_USE:
535 default:
536 length = sprintf(buff, "not in use\n");
537 break;
538 }
539
540 kref_put(&batman_if->refcount, hardif_free_ref);
541
542 return length;
543}
544
545static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
546 show_mesh_iface, store_mesh_iface);
547static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
548
549static struct bat_attribute *batman_attrs[] = {
550 &bat_attr_mesh_iface,
551 &bat_attr_iface_status,
552 NULL,
553};
554
555int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
556{
557 struct kobject *hardif_kobject = &dev->dev.kobj;
558 struct bat_attribute **bat_attr;
559 int err;
560
561 *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
562 hardif_kobject);
563
564 if (!*hardif_obj) {
565 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
566 SYSFS_IF_BAT_SUBDIR);
567 goto out;
568 }
569
570 for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
571 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
572 if (err) {
573 bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
574 dev->name, SYSFS_IF_BAT_SUBDIR,
575 ((*bat_attr)->attr).name);
576 goto rem_attr;
577 }
578 }
579
580 return 0;
581
582rem_attr:
583 for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
584 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
585out:
586 return -ENOMEM;
587}
588
589void sysfs_del_hardif(struct kobject **hardif_obj)
590{
591 kobject_put(*hardif_obj);
592 *hardif_obj = NULL;
593}
diff --git a/drivers/staging/batman-adv/bat_sysfs.h b/drivers/staging/batman-adv/bat_sysfs.h
deleted file mode 100644
index 7f186c007b4f..000000000000
--- a/drivers/staging/batman-adv/bat_sysfs.h
+++ /dev/null
@@ -1,42 +0,0 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22
23#ifndef _NET_BATMAN_ADV_SYSFS_H_
24#define _NET_BATMAN_ADV_SYSFS_H_
25
26#define SYSFS_IF_MESH_SUBDIR "mesh"
27#define SYSFS_IF_BAT_SUBDIR "batman_adv"
28
29struct bat_attribute {
30 struct attribute attr;
31 ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
32 char *buf);
33 ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
34 char *buf, size_t count);
35};
36
37int sysfs_add_meshif(struct net_device *dev);
38void sysfs_del_meshif(struct net_device *dev);
39int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
40void sysfs_del_hardif(struct kobject **hardif_obj);
41
42#endif /* _NET_BATMAN_ADV_SYSFS_H_ */
diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c
deleted file mode 100644
index 814274fbaa2f..000000000000
--- a/drivers/staging/batman-adv/bitarray.c
+++ /dev/null
@@ -1,201 +0,0 @@
1/*
2 * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich, Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "bitarray.h"
24
25#include <linux/bitops.h>
26
27/* returns true if the corresponding bit in the given seq_bits indicates true
28 * and curr_seqno is within range of last_seqno */
29uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
30 uint32_t curr_seqno)
31{
32 int32_t diff, word_offset, word_num;
33
34 diff = last_seqno - curr_seqno;
35 if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) {
36 return 0;
37 } else {
38 /* which word */
39 word_num = (last_seqno - curr_seqno) / WORD_BIT_SIZE;
40 /* which position in the selected word */
41 word_offset = (last_seqno - curr_seqno) % WORD_BIT_SIZE;
42
43 if (seq_bits[word_num] & 1 << word_offset)
44 return 1;
45 else
46 return 0;
47 }
48}
49
50/* turn corresponding bit on, so we can remember that we got the packet */
51void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n)
52{
53 int32_t word_offset, word_num;
54
55 /* if too old, just drop it */
56 if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE)
57 return;
58
59 /* which word */
60 word_num = n / WORD_BIT_SIZE;
61 /* which position in the selected word */
62 word_offset = n % WORD_BIT_SIZE;
63
64 seq_bits[word_num] |= 1 << word_offset; /* turn the position on */
65}
66
67/* shift the packet array by n places. */
68static void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
69{
70 int32_t word_offset, word_num;
71 int32_t i;
72
73 if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE)
74 return;
75
76 word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */
77 word_num = n / WORD_BIT_SIZE; /* shift over how much (full) words */
78
79 for (i = NUM_WORDS - 1; i > word_num; i--) {
80 /* going from old to new, so we don't overwrite the data we copy
81 * from.
82 *
83 * left is high, right is low: FEDC BA98 7654 3210
84 * ^^ ^^
85 * vvvv
86 * ^^^^ = from, vvvvv =to, we'd have word_num==1 and
87 * word_offset==WORD_BIT_SIZE/2 ????? in this example.
88 * (=24 bits)
89 *
90 * our desired output would be: 9876 5432 1000 0000
91 * */
92
93 seq_bits[i] =
94 (seq_bits[i - word_num] << word_offset) +
95 /* take the lower port from the left half, shift it left
96 * to its final position */
97 (seq_bits[i - word_num - 1] >>
98 (WORD_BIT_SIZE-word_offset));
99 /* and the upper part of the right half and shift it left to
100 * it's position */
101 /* for our example that would be: word[0] = 9800 + 0076 =
102 * 9876 */
103 }
104 /* now for our last word, i==word_num, we only have the it's "left"
105 * half. that's the 1000 word in our example.*/
106
107 seq_bits[i] = (seq_bits[i - word_num] << word_offset);
108
109 /* pad the rest with 0, if there is anything */
110 i--;
111
112 for (; i >= 0; i--)
113 seq_bits[i] = 0;
114}
115
116static void bit_reset_window(TYPE_OF_WORD *seq_bits)
117{
118 int i;
119 for (i = 0; i < NUM_WORDS; i++)
120 seq_bits[i] = 0;
121}
122
123
124/* receive and process one packet within the sequence number window.
125 *
126 * returns:
127 * 1 if the window was moved (either new or very old)
128 * 0 if the window was not moved/shifted.
129 */
130char bit_get_packet(void *priv, TYPE_OF_WORD *seq_bits,
131 int32_t seq_num_diff, int8_t set_mark)
132{
133 struct bat_priv *bat_priv = (struct bat_priv *)priv;
134
135 /* sequence number is slightly older. We already got a sequence number
136 * higher than this one, so we just mark it. */
137
138 if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) {
139 if (set_mark)
140 bit_mark(seq_bits, -seq_num_diff);
141 return 0;
142 }
143
144 /* sequence number is slightly newer, so we shift the window and
145 * set the mark if required */
146
147 if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) {
148 bit_shift(seq_bits, seq_num_diff);
149
150 if (set_mark)
151 bit_mark(seq_bits, 0);
152 return 1;
153 }
154
155 /* sequence number is much newer, probably missed a lot of packets */
156
157 if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
158 || (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
159 bat_dbg(DBG_BATMAN, bat_priv,
160 "We missed a lot of packets (%i) !\n",
161 seq_num_diff - 1);
162 bit_reset_window(seq_bits);
163 if (set_mark)
164 bit_mark(seq_bits, 0);
165 return 1;
166 }
167
168 /* received a much older packet. The other host either restarted
169 * or the old packet got delayed somewhere in the network. The
170 * packet should be dropped without calling this function if the
171 * seqno window is protected. */
172
173 if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
174 || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
175
176 bat_dbg(DBG_BATMAN, bat_priv,
177 "Other host probably restarted!\n");
178
179 bit_reset_window(seq_bits);
180 if (set_mark)
181 bit_mark(seq_bits, 0);
182
183 return 1;
184 }
185
186 /* never reached */
187 return 0;
188}
189
190/* count the hamming weight, how many good packets did we receive? just count
191 * the 1's.
192 */
193int bit_packet_count(TYPE_OF_WORD *seq_bits)
194{
195 int i, hamming = 0;
196
197 for (i = 0; i < NUM_WORDS; i++)
198 hamming += hweight_long(seq_bits[i]);
199
200 return hamming;
201}
diff --git a/drivers/staging/batman-adv/bitarray.h b/drivers/staging/batman-adv/bitarray.h
deleted file mode 100644
index 77b1e61847e8..000000000000
--- a/drivers/staging/batman-adv/bitarray.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich, Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_BITARRAY_H_
23#define _NET_BATMAN_ADV_BITARRAY_H_
24
25/* you should choose something big, if you don't want to waste cpu
26 * and keep the type in sync with bit_packet_count */
27#define TYPE_OF_WORD unsigned long
28#define WORD_BIT_SIZE (sizeof(TYPE_OF_WORD) * 8)
29
30/* returns true if the corresponding bit in the given seq_bits indicates true
31 * and curr_seqno is within range of last_seqno */
32uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
33 uint32_t curr_seqno);
34
35/* turn corresponding bit on, so we can remember that we got the packet */
36void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n);
37
38
39/* receive and process one packet, returns 1 if received seq_num is considered
40 * new, 0 if old */
41char bit_get_packet(void *priv, TYPE_OF_WORD *seq_bits,
42 int32_t seq_num_diff, int8_t set_mark);
43
44/* count the hamming weight, how many good packets did we receive? */
45int bit_packet_count(TYPE_OF_WORD *seq_bits);
46
47#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
diff --git a/drivers/staging/batman-adv/gateway_client.c b/drivers/staging/batman-adv/gateway_client.c
deleted file mode 100644
index 0065ffb8d96d..000000000000
--- a/drivers/staging/batman-adv/gateway_client.c
+++ /dev/null
@@ -1,477 +0,0 @@
1/*
2 * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "gateway_client.h"
24#include "gateway_common.h"
25#include "hard-interface.h"
26#include <linux/ip.h>
27#include <linux/ipv6.h>
28#include <linux/udp.h>
29#include <linux/if_vlan.h>
30
31static void gw_node_free_ref(struct kref *refcount)
32{
33 struct gw_node *gw_node;
34
35 gw_node = container_of(refcount, struct gw_node, refcount);
36 kfree(gw_node);
37}
38
39static void gw_node_free_rcu(struct rcu_head *rcu)
40{
41 struct gw_node *gw_node;
42
43 gw_node = container_of(rcu, struct gw_node, rcu);
44 kref_put(&gw_node->refcount, gw_node_free_ref);
45}
46
47void *gw_get_selected(struct bat_priv *bat_priv)
48{
49 struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
50
51 if (!curr_gateway_tmp)
52 return NULL;
53
54 return curr_gateway_tmp->orig_node;
55}
56
57void gw_deselect(struct bat_priv *bat_priv)
58{
59 struct gw_node *gw_node = bat_priv->curr_gw;
60
61 bat_priv->curr_gw = NULL;
62
63 if (gw_node)
64 kref_put(&gw_node->refcount, gw_node_free_ref);
65}
66
67static struct gw_node *gw_select(struct bat_priv *bat_priv,
68 struct gw_node *new_gw_node)
69{
70 struct gw_node *curr_gw_node = bat_priv->curr_gw;
71
72 if (new_gw_node)
73 kref_get(&new_gw_node->refcount);
74
75 bat_priv->curr_gw = new_gw_node;
76 return curr_gw_node;
77}
78
79void gw_election(struct bat_priv *bat_priv)
80{
81 struct hlist_node *node;
82 struct gw_node *gw_node, *curr_gw_tmp = NULL, *old_gw_node = NULL;
83 uint8_t max_tq = 0;
84 uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
85 int down, up;
86
87 /**
88 * The batman daemon checks here if we already passed a full originator
89 * cycle in order to make sure we don't choose the first gateway we
90 * hear about. This check is based on the daemon's uptime which we
91 * don't have.
92 **/
93 if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
94 return;
95
96 if (bat_priv->curr_gw)
97 return;
98
99 rcu_read_lock();
100 if (hlist_empty(&bat_priv->gw_list)) {
101 rcu_read_unlock();
102
103 if (bat_priv->curr_gw) {
104 bat_dbg(DBG_BATMAN, bat_priv,
105 "Removing selected gateway - "
106 "no gateway in range\n");
107 gw_deselect(bat_priv);
108 }
109
110 return;
111 }
112
113 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
114 if (!gw_node->orig_node->router)
115 continue;
116
117 if (gw_node->deleted)
118 continue;
119
120 switch (atomic_read(&bat_priv->gw_sel_class)) {
121 case 1: /* fast connection */
122 gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags,
123 &down, &up);
124
125 tmp_gw_factor = (gw_node->orig_node->router->tq_avg *
126 gw_node->orig_node->router->tq_avg *
127 down * 100 * 100) /
128 (TQ_LOCAL_WINDOW_SIZE *
129 TQ_LOCAL_WINDOW_SIZE * 64);
130
131 if ((tmp_gw_factor > max_gw_factor) ||
132 ((tmp_gw_factor == max_gw_factor) &&
133 (gw_node->orig_node->router->tq_avg > max_tq)))
134 curr_gw_tmp = gw_node;
135 break;
136
137 default: /**
138 * 2: stable connection (use best statistic)
139 * 3: fast-switch (use best statistic but change as
140 * soon as a better gateway appears)
141 * XX: late-switch (use best statistic but change as
142 * soon as a better gateway appears which has
143 * $routing_class more tq points)
144 **/
145 if (gw_node->orig_node->router->tq_avg > max_tq)
146 curr_gw_tmp = gw_node;
147 break;
148 }
149
150 if (gw_node->orig_node->router->tq_avg > max_tq)
151 max_tq = gw_node->orig_node->router->tq_avg;
152
153 if (tmp_gw_factor > max_gw_factor)
154 max_gw_factor = tmp_gw_factor;
155 }
156
157 if (bat_priv->curr_gw != curr_gw_tmp) {
158 if ((bat_priv->curr_gw) && (!curr_gw_tmp))
159 bat_dbg(DBG_BATMAN, bat_priv,
160 "Removing selected gateway - "
161 "no gateway in range\n");
162 else if ((!bat_priv->curr_gw) && (curr_gw_tmp))
163 bat_dbg(DBG_BATMAN, bat_priv,
164 "Adding route to gateway %pM "
165 "(gw_flags: %i, tq: %i)\n",
166 curr_gw_tmp->orig_node->orig,
167 curr_gw_tmp->orig_node->gw_flags,
168 curr_gw_tmp->orig_node->router->tq_avg);
169 else
170 bat_dbg(DBG_BATMAN, bat_priv,
171 "Changing route to gateway %pM "
172 "(gw_flags: %i, tq: %i)\n",
173 curr_gw_tmp->orig_node->orig,
174 curr_gw_tmp->orig_node->gw_flags,
175 curr_gw_tmp->orig_node->router->tq_avg);
176
177 old_gw_node = gw_select(bat_priv, curr_gw_tmp);
178 }
179
180 rcu_read_unlock();
181
182 /* the kfree() has to be outside of the rcu lock */
183 if (old_gw_node)
184 kref_put(&old_gw_node->refcount, gw_node_free_ref);
185}
186
187void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
188{
189 struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
190 uint8_t gw_tq_avg, orig_tq_avg;
191
192 if (!curr_gateway_tmp)
193 return;
194
195 if (!curr_gateway_tmp->orig_node)
196 goto deselect;
197
198 if (!curr_gateway_tmp->orig_node->router)
199 goto deselect;
200
201 /* this node already is the gateway */
202 if (curr_gateway_tmp->orig_node == orig_node)
203 return;
204
205 if (!orig_node->router)
206 return;
207
208 gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg;
209 orig_tq_avg = orig_node->router->tq_avg;
210
211 /* the TQ value has to be better */
212 if (orig_tq_avg < gw_tq_avg)
213 return;
214
215 /**
216 * if the routing class is greater than 3 the value tells us how much
217 * greater the TQ value of the new gateway must be
218 **/
219 if ((atomic_read(&bat_priv->gw_sel_class) > 3) &&
220 (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class)))
221 return;
222
223 bat_dbg(DBG_BATMAN, bat_priv,
224 "Restarting gateway selection: better gateway found (tq curr: "
225 "%i, tq new: %i)\n",
226 gw_tq_avg, orig_tq_avg);
227
228deselect:
229 gw_deselect(bat_priv);
230}
231
232static void gw_node_add(struct bat_priv *bat_priv,
233 struct orig_node *orig_node, uint8_t new_gwflags)
234{
235 struct gw_node *gw_node;
236 int down, up;
237
238 gw_node = kmalloc(sizeof(struct gw_node), GFP_ATOMIC);
239 if (!gw_node)
240 return;
241
242 memset(gw_node, 0, sizeof(struct gw_node));
243 INIT_HLIST_NODE(&gw_node->list);
244 gw_node->orig_node = orig_node;
245 kref_init(&gw_node->refcount);
246
247 spin_lock_bh(&bat_priv->gw_list_lock);
248 hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
249 spin_unlock_bh(&bat_priv->gw_list_lock);
250
251 gw_bandwidth_to_kbit(new_gwflags, &down, &up);
252 bat_dbg(DBG_BATMAN, bat_priv,
253 "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n",
254 orig_node->orig, new_gwflags,
255 (down > 2048 ? down / 1024 : down),
256 (down > 2048 ? "MBit" : "KBit"),
257 (up > 2048 ? up / 1024 : up),
258 (up > 2048 ? "MBit" : "KBit"));
259}
260
261void gw_node_update(struct bat_priv *bat_priv,
262 struct orig_node *orig_node, uint8_t new_gwflags)
263{
264 struct hlist_node *node;
265 struct gw_node *gw_node;
266
267 rcu_read_lock();
268 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
269 if (gw_node->orig_node != orig_node)
270 continue;
271
272 bat_dbg(DBG_BATMAN, bat_priv,
273 "Gateway class of originator %pM changed from "
274 "%i to %i\n",
275 orig_node->orig, gw_node->orig_node->gw_flags,
276 new_gwflags);
277
278 gw_node->deleted = 0;
279
280 if (new_gwflags == 0) {
281 gw_node->deleted = jiffies;
282 bat_dbg(DBG_BATMAN, bat_priv,
283 "Gateway %pM removed from gateway list\n",
284 orig_node->orig);
285
286 if (gw_node == bat_priv->curr_gw) {
287 rcu_read_unlock();
288 gw_deselect(bat_priv);
289 return;
290 }
291 }
292
293 rcu_read_unlock();
294 return;
295 }
296 rcu_read_unlock();
297
298 if (new_gwflags == 0)
299 return;
300
301 gw_node_add(bat_priv, orig_node, new_gwflags);
302}
303
304void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
305{
306 return gw_node_update(bat_priv, orig_node, 0);
307}
308
309void gw_node_purge(struct bat_priv *bat_priv)
310{
311 struct gw_node *gw_node;
312 struct hlist_node *node, *node_tmp;
313 unsigned long timeout = 2 * PURGE_TIMEOUT * HZ;
314
315 spin_lock_bh(&bat_priv->gw_list_lock);
316
317 hlist_for_each_entry_safe(gw_node, node, node_tmp,
318 &bat_priv->gw_list, list) {
319 if (((!gw_node->deleted) ||
320 (time_before(jiffies, gw_node->deleted + timeout))) &&
321 atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)
322 continue;
323
324 if (bat_priv->curr_gw == gw_node)
325 gw_deselect(bat_priv);
326
327 hlist_del_rcu(&gw_node->list);
328 call_rcu(&gw_node->rcu, gw_node_free_rcu);
329 }
330
331
332 spin_unlock_bh(&bat_priv->gw_list_lock);
333}
334
335static int _write_buffer_text(struct bat_priv *bat_priv,
336 struct seq_file *seq, struct gw_node *gw_node)
337{
338 int down, up;
339
340 gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
341
342 return seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
343 (bat_priv->curr_gw == gw_node ? "=>" : " "),
344 gw_node->orig_node->orig,
345 gw_node->orig_node->router->tq_avg,
346 gw_node->orig_node->router->addr,
347 gw_node->orig_node->router->if_incoming->net_dev->name,
348 gw_node->orig_node->gw_flags,
349 (down > 2048 ? down / 1024 : down),
350 (down > 2048 ? "MBit" : "KBit"),
351 (up > 2048 ? up / 1024 : up),
352 (up > 2048 ? "MBit" : "KBit"));
353}
354
355int gw_client_seq_print_text(struct seq_file *seq, void *offset)
356{
357 struct net_device *net_dev = (struct net_device *)seq->private;
358 struct bat_priv *bat_priv = netdev_priv(net_dev);
359 struct gw_node *gw_node;
360 struct hlist_node *node;
361 int gw_count = 0;
362
363 if (!bat_priv->primary_if) {
364
365 return seq_printf(seq, "BATMAN mesh %s disabled - please "
366 "specify interfaces to enable it\n",
367 net_dev->name);
368 }
369
370 if (bat_priv->primary_if->if_status != IF_ACTIVE) {
371
372 return seq_printf(seq, "BATMAN mesh %s disabled - "
373 "primary interface not active\n",
374 net_dev->name);
375 }
376
377 seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "
378 "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
379 "Gateway", "#", TQ_MAX_VALUE, "Nexthop",
380 "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
381 bat_priv->primary_if->net_dev->name,
382 bat_priv->primary_if->net_dev->dev_addr, net_dev->name);
383
384 rcu_read_lock();
385 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
386 if (gw_node->deleted)
387 continue;
388
389 if (!gw_node->orig_node->router)
390 continue;
391
392 _write_buffer_text(bat_priv, seq, gw_node);
393 gw_count++;
394 }
395 rcu_read_unlock();
396
397 if (gw_count == 0)
398 seq_printf(seq, "No gateways in range ...\n");
399
400 return 0;
401}
402
403int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
404{
405 struct ethhdr *ethhdr;
406 struct iphdr *iphdr;
407 struct ipv6hdr *ipv6hdr;
408 struct udphdr *udphdr;
409 unsigned int header_len = 0;
410
411 if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF)
412 return 0;
413
414 /* check for ethernet header */
415 if (!pskb_may_pull(skb, header_len + ETH_HLEN))
416 return 0;
417 ethhdr = (struct ethhdr *)skb->data;
418 header_len += ETH_HLEN;
419
420 /* check for initial vlan header */
421 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
422 if (!pskb_may_pull(skb, header_len + VLAN_HLEN))
423 return 0;
424 ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
425 header_len += VLAN_HLEN;
426 }
427
428 /* check for ip header */
429 switch (ntohs(ethhdr->h_proto)) {
430 case ETH_P_IP:
431 if (!pskb_may_pull(skb, header_len + sizeof(struct iphdr)))
432 return 0;
433 iphdr = (struct iphdr *)(skb->data + header_len);
434 header_len += iphdr->ihl * 4;
435
436 /* check for udp header */
437 if (iphdr->protocol != IPPROTO_UDP)
438 return 0;
439
440 break;
441 case ETH_P_IPV6:
442 if (!pskb_may_pull(skb, header_len + sizeof(struct ipv6hdr)))
443 return 0;
444 ipv6hdr = (struct ipv6hdr *)(skb->data + header_len);
445 header_len += sizeof(struct ipv6hdr);
446
447 /* check for udp header */
448 if (ipv6hdr->nexthdr != IPPROTO_UDP)
449 return 0;
450
451 break;
452 default:
453 return 0;
454 }
455
456 if (!pskb_may_pull(skb, header_len + sizeof(struct udphdr)))
457 return 0;
458 udphdr = (struct udphdr *)(skb->data + header_len);
459 header_len += sizeof(struct udphdr);
460
461 /* check for bootp port */
462 if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
463 (ntohs(udphdr->dest) != 67))
464 return 0;
465
466 if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) &&
467 (ntohs(udphdr->dest) != 547))
468 return 0;
469
470 if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)
471 return -1;
472
473 if (!bat_priv->curr_gw)
474 return 0;
475
476 return 1;
477}
diff --git a/drivers/staging/batman-adv/gateway_client.h b/drivers/staging/batman-adv/gateway_client.h
deleted file mode 100644
index 4585e6549844..000000000000
--- a/drivers/staging/batman-adv/gateway_client.h
+++ /dev/null
@@ -1,36 +0,0 @@
1/*
2 * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_GATEWAY_CLIENT_H_
23#define _NET_BATMAN_ADV_GATEWAY_CLIENT_H_
24
25void gw_deselect(struct bat_priv *bat_priv);
26void gw_election(struct bat_priv *bat_priv);
27void *gw_get_selected(struct bat_priv *bat_priv);
28void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node);
29void gw_node_update(struct bat_priv *bat_priv,
30 struct orig_node *orig_node, uint8_t new_gwflags);
31void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node);
32void gw_node_purge(struct bat_priv *bat_priv);
33int gw_client_seq_print_text(struct seq_file *seq, void *offset);
34int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb);
35
36#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
diff --git a/drivers/staging/batman-adv/gateway_common.c b/drivers/staging/batman-adv/gateway_common.c
deleted file mode 100644
index b962982f017e..000000000000
--- a/drivers/staging/batman-adv/gateway_common.c
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2 * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "gateway_common.h"
24#include "gateway_client.h"
25
26/* calculates the gateway class from kbit */
27static void kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class)
28{
29 int mdown = 0, tdown, tup, difference;
30 uint8_t sbit, part;
31
32 *gw_srv_class = 0;
33 difference = 0x0FFFFFFF;
34
35 /* test all downspeeds */
36 for (sbit = 0; sbit < 2; sbit++) {
37 for (part = 0; part < 16; part++) {
38 tdown = 32 * (sbit + 2) * (1 << part);
39
40 if (abs(tdown - down) < difference) {
41 *gw_srv_class = (sbit << 7) + (part << 3);
42 difference = abs(tdown - down);
43 mdown = tdown;
44 }
45 }
46 }
47
48 /* test all upspeeds */
49 difference = 0x0FFFFFFF;
50
51 for (part = 0; part < 8; part++) {
52 tup = ((part + 1) * (mdown)) / 8;
53
54 if (abs(tup - up) < difference) {
55 *gw_srv_class = (*gw_srv_class & 0xF8) | part;
56 difference = abs(tup - up);
57 }
58 }
59}
60
61/* returns the up and downspeeds in kbit, calculated from the class */
62void gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up)
63{
64 char sbit = (gw_srv_class & 0x80) >> 7;
65 char dpart = (gw_srv_class & 0x78) >> 3;
66 char upart = (gw_srv_class & 0x07);
67
68 if (!gw_srv_class) {
69 *down = 0;
70 *up = 0;
71 return;
72 }
73
74 *down = 32 * (sbit + 2) * (1 << dpart);
75 *up = ((upart + 1) * (*down)) / 8;
76}
77
78static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
79 long *up, long *down)
80{
81 int ret, multi = 1;
82 char *slash_ptr, *tmp_ptr;
83
84 slash_ptr = strchr(buff, '/');
85 if (slash_ptr)
86 *slash_ptr = 0;
87
88 if (strlen(buff) > 4) {
89 tmp_ptr = buff + strlen(buff) - 4;
90
91 if (strnicmp(tmp_ptr, "mbit", 4) == 0)
92 multi = 1024;
93
94 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
95 (multi > 1))
96 *tmp_ptr = '\0';
97 }
98
99 ret = strict_strtoul(buff, 10, down);
100 if (ret) {
101 bat_err(net_dev,
102 "Download speed of gateway mode invalid: %s\n",
103 buff);
104 return false;
105 }
106
107 *down *= multi;
108
109 /* we also got some upload info */
110 if (slash_ptr) {
111 multi = 1;
112
113 if (strlen(slash_ptr + 1) > 4) {
114 tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1);
115
116 if (strnicmp(tmp_ptr, "mbit", 4) == 0)
117 multi = 1024;
118
119 if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
120 (multi > 1))
121 *tmp_ptr = '\0';
122 }
123
124 ret = strict_strtoul(slash_ptr + 1, 10, up);
125 if (ret) {
126 bat_err(net_dev,
127 "Upload speed of gateway mode invalid: "
128 "%s\n", slash_ptr + 1);
129 return false;
130 }
131
132 *up *= multi;
133 }
134
135 return true;
136}
137
138ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count)
139{
140 struct bat_priv *bat_priv = netdev_priv(net_dev);
141 long gw_bandwidth_tmp = 0, up = 0, down = 0;
142 bool ret;
143
144 ret = parse_gw_bandwidth(net_dev, buff, &up, &down);
145 if (!ret)
146 goto end;
147
148 if ((!down) || (down < 256))
149 down = 2000;
150
151 if (!up)
152 up = down / 5;
153
154 kbit_to_gw_bandwidth(down, up, &gw_bandwidth_tmp);
155
156 /**
157 * the gw bandwidth we guessed above might not match the given
158 * speeds, hence we need to calculate it back to show the number
159 * that is going to be propagated
160 **/
161 gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp,
162 (int *)&down, (int *)&up);
163
164 gw_deselect(bat_priv);
165 bat_info(net_dev, "Changing gateway bandwidth from: '%i' to: '%ld' "
166 "(propagating: %ld%s/%ld%s)\n",
167 atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp,
168 (down > 2048 ? down / 1024 : down),
169 (down > 2048 ? "MBit" : "KBit"),
170 (up > 2048 ? up / 1024 : up),
171 (up > 2048 ? "MBit" : "KBit"));
172
173 atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp);
174
175end:
176 return count;
177}
diff --git a/drivers/staging/batman-adv/gateway_common.h b/drivers/staging/batman-adv/gateway_common.h
deleted file mode 100644
index 5e728d0b7959..000000000000
--- a/drivers/staging/batman-adv/gateway_common.h
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_GATEWAY_COMMON_H_
23#define _NET_BATMAN_ADV_GATEWAY_COMMON_H_
24
25enum gw_modes {
26 GW_MODE_OFF,
27 GW_MODE_CLIENT,
28 GW_MODE_SERVER,
29};
30
31#define GW_MODE_OFF_NAME "off"
32#define GW_MODE_CLIENT_NAME "client"
33#define GW_MODE_SERVER_NAME "server"
34
35void gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up);
36ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count);
37
38#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c
deleted file mode 100644
index c3c7b7ac0946..000000000000
--- a/drivers/staging/batman-adv/hard-interface.c
+++ /dev/null
@@ -1,652 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "hard-interface.h"
24#include "soft-interface.h"
25#include "send.h"
26#include "translation-table.h"
27#include "routing.h"
28#include "bat_sysfs.h"
29#include "originator.h"
30#include "hash.h"
31
32#include <linux/if_arp.h>
33
34/* protect update critical side of if_list - but not the content */
35static DEFINE_SPINLOCK(if_list_lock);
36
37static void hardif_free_rcu(struct rcu_head *rcu)
38{
39 struct batman_if *batman_if;
40
41 batman_if = container_of(rcu, struct batman_if, rcu);
42 dev_put(batman_if->net_dev);
43 kref_put(&batman_if->refcount, hardif_free_ref);
44}
45
46struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
47{
48 struct batman_if *batman_if;
49
50 rcu_read_lock();
51 list_for_each_entry_rcu(batman_if, &if_list, list) {
52 if (batman_if->net_dev == net_dev)
53 goto out;
54 }
55
56 batman_if = NULL;
57
58out:
59 if (batman_if)
60 kref_get(&batman_if->refcount);
61
62 rcu_read_unlock();
63 return batman_if;
64}
65
66static int is_valid_iface(struct net_device *net_dev)
67{
68 if (net_dev->flags & IFF_LOOPBACK)
69 return 0;
70
71 if (net_dev->type != ARPHRD_ETHER)
72 return 0;
73
74 if (net_dev->addr_len != ETH_ALEN)
75 return 0;
76
77 /* no batman over batman */
78#ifdef HAVE_NET_DEVICE_OPS
79 if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
80 return 0;
81#else
82 if (net_dev->hard_start_xmit == interface_tx)
83 return 0;
84#endif
85
86 /* Device is being bridged */
87 /* if (net_dev->priv_flags & IFF_BRIDGE_PORT)
88 return 0; */
89
90 return 1;
91}
92
93static struct batman_if *get_active_batman_if(struct net_device *soft_iface)
94{
95 struct batman_if *batman_if;
96
97 rcu_read_lock();
98 list_for_each_entry_rcu(batman_if, &if_list, list) {
99 if (batman_if->soft_iface != soft_iface)
100 continue;
101
102 if (batman_if->if_status == IF_ACTIVE)
103 goto out;
104 }
105
106 batman_if = NULL;
107
108out:
109 if (batman_if)
110 kref_get(&batman_if->refcount);
111
112 rcu_read_unlock();
113 return batman_if;
114}
115
116static void update_primary_addr(struct bat_priv *bat_priv)
117{
118 struct vis_packet *vis_packet;
119
120 vis_packet = (struct vis_packet *)
121 bat_priv->my_vis_info->skb_packet->data;
122 memcpy(vis_packet->vis_orig,
123 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
124 memcpy(vis_packet->sender_orig,
125 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
126}
127
128static void set_primary_if(struct bat_priv *bat_priv,
129 struct batman_if *batman_if)
130{
131 struct batman_packet *batman_packet;
132 struct batman_if *old_if;
133
134 if (batman_if)
135 kref_get(&batman_if->refcount);
136
137 old_if = bat_priv->primary_if;
138 bat_priv->primary_if = batman_if;
139
140 if (old_if)
141 kref_put(&old_if->refcount, hardif_free_ref);
142
143 if (!bat_priv->primary_if)
144 return;
145
146 batman_packet = (struct batman_packet *)(batman_if->packet_buff);
147 batman_packet->flags = PRIMARIES_FIRST_HOP;
148 batman_packet->ttl = TTL;
149
150 update_primary_addr(bat_priv);
151
152 /***
153 * hacky trick to make sure that we send the HNA information via
154 * our new primary interface
155 */
156 atomic_set(&bat_priv->hna_local_changed, 1);
157}
158
159static bool hardif_is_iface_up(struct batman_if *batman_if)
160{
161 if (batman_if->net_dev->flags & IFF_UP)
162 return true;
163
164 return false;
165}
166
167static void update_mac_addresses(struct batman_if *batman_if)
168{
169 memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
170 batman_if->net_dev->dev_addr, ETH_ALEN);
171 memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
172 batman_if->net_dev->dev_addr, ETH_ALEN);
173}
174
175static void check_known_mac_addr(struct net_device *net_dev)
176{
177 struct batman_if *batman_if;
178
179 rcu_read_lock();
180 list_for_each_entry_rcu(batman_if, &if_list, list) {
181 if ((batman_if->if_status != IF_ACTIVE) &&
182 (batman_if->if_status != IF_TO_BE_ACTIVATED))
183 continue;
184
185 if (batman_if->net_dev == net_dev)
186 continue;
187
188 if (!compare_orig(batman_if->net_dev->dev_addr,
189 net_dev->dev_addr))
190 continue;
191
192 pr_warning("The newly added mac address (%pM) already exists "
193 "on: %s\n", net_dev->dev_addr,
194 batman_if->net_dev->name);
195 pr_warning("It is strongly recommended to keep mac addresses "
196 "unique to avoid problems!\n");
197 }
198 rcu_read_unlock();
199}
200
201int hardif_min_mtu(struct net_device *soft_iface)
202{
203 struct bat_priv *bat_priv = netdev_priv(soft_iface);
204 struct batman_if *batman_if;
205 /* allow big frames if all devices are capable to do so
206 * (have MTU > 1500 + BAT_HEADER_LEN) */
207 int min_mtu = ETH_DATA_LEN;
208
209 if (atomic_read(&bat_priv->fragmentation))
210 goto out;
211
212 rcu_read_lock();
213 list_for_each_entry_rcu(batman_if, &if_list, list) {
214 if ((batman_if->if_status != IF_ACTIVE) &&
215 (batman_if->if_status != IF_TO_BE_ACTIVATED))
216 continue;
217
218 if (batman_if->soft_iface != soft_iface)
219 continue;
220
221 min_mtu = min_t(int, batman_if->net_dev->mtu - BAT_HEADER_LEN,
222 min_mtu);
223 }
224 rcu_read_unlock();
225out:
226 return min_mtu;
227}
228
229/* adjusts the MTU if a new interface with a smaller MTU appeared. */
230void update_min_mtu(struct net_device *soft_iface)
231{
232 int min_mtu;
233
234 min_mtu = hardif_min_mtu(soft_iface);
235 if (soft_iface->mtu != min_mtu)
236 soft_iface->mtu = min_mtu;
237}
238
239static void hardif_activate_interface(struct batman_if *batman_if)
240{
241 struct bat_priv *bat_priv;
242
243 if (batman_if->if_status != IF_INACTIVE)
244 return;
245
246 bat_priv = netdev_priv(batman_if->soft_iface);
247
248 update_mac_addresses(batman_if);
249 batman_if->if_status = IF_TO_BE_ACTIVATED;
250
251 /**
252 * the first active interface becomes our primary interface or
253 * the next active interface after the old primay interface was removed
254 */
255 if (!bat_priv->primary_if)
256 set_primary_if(bat_priv, batman_if);
257
258 bat_info(batman_if->soft_iface, "Interface activated: %s\n",
259 batman_if->net_dev->name);
260
261 update_min_mtu(batman_if->soft_iface);
262 return;
263}
264
265static void hardif_deactivate_interface(struct batman_if *batman_if)
266{
267 if ((batman_if->if_status != IF_ACTIVE) &&
268 (batman_if->if_status != IF_TO_BE_ACTIVATED))
269 return;
270
271 batman_if->if_status = IF_INACTIVE;
272
273 bat_info(batman_if->soft_iface, "Interface deactivated: %s\n",
274 batman_if->net_dev->name);
275
276 update_min_mtu(batman_if->soft_iface);
277}
278
279int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
280{
281 struct bat_priv *bat_priv;
282 struct batman_packet *batman_packet;
283
284 if (batman_if->if_status != IF_NOT_IN_USE)
285 goto out;
286
287 batman_if->soft_iface = dev_get_by_name(&init_net, iface_name);
288
289 if (!batman_if->soft_iface) {
290 batman_if->soft_iface = softif_create(iface_name);
291
292 if (!batman_if->soft_iface)
293 goto err;
294
295 /* dev_get_by_name() increases the reference counter for us */
296 dev_hold(batman_if->soft_iface);
297 }
298
299 bat_priv = netdev_priv(batman_if->soft_iface);
300 batman_if->packet_len = BAT_PACKET_LEN;
301 batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
302
303 if (!batman_if->packet_buff) {
304 bat_err(batman_if->soft_iface, "Can't add interface packet "
305 "(%s): out of memory\n", batman_if->net_dev->name);
306 goto err;
307 }
308
309 batman_packet = (struct batman_packet *)(batman_if->packet_buff);
310 batman_packet->packet_type = BAT_PACKET;
311 batman_packet->version = COMPAT_VERSION;
312 batman_packet->flags = 0;
313 batman_packet->ttl = 2;
314 batman_packet->tq = TQ_MAX_VALUE;
315 batman_packet->num_hna = 0;
316
317 batman_if->if_num = bat_priv->num_ifaces;
318 bat_priv->num_ifaces++;
319 batman_if->if_status = IF_INACTIVE;
320 orig_hash_add_if(batman_if, bat_priv->num_ifaces);
321
322 batman_if->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN);
323 batman_if->batman_adv_ptype.func = batman_skb_recv;
324 batman_if->batman_adv_ptype.dev = batman_if->net_dev;
325 kref_get(&batman_if->refcount);
326 dev_add_pack(&batman_if->batman_adv_ptype);
327
328 atomic_set(&batman_if->seqno, 1);
329 atomic_set(&batman_if->frag_seqno, 1);
330 bat_info(batman_if->soft_iface, "Adding interface: %s\n",
331 batman_if->net_dev->name);
332
333 if (atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu <
334 ETH_DATA_LEN + BAT_HEADER_LEN)
335 bat_info(batman_if->soft_iface,
336 "The MTU of interface %s is too small (%i) to handle "
337 "the transport of batman-adv packets. Packets going "
338 "over this interface will be fragmented on layer2 "
339 "which could impact the performance. Setting the MTU "
340 "to %zi would solve the problem.\n",
341 batman_if->net_dev->name, batman_if->net_dev->mtu,
342 ETH_DATA_LEN + BAT_HEADER_LEN);
343
344 if (!atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu <
345 ETH_DATA_LEN + BAT_HEADER_LEN)
346 bat_info(batman_if->soft_iface,
347 "The MTU of interface %s is too small (%i) to handle "
348 "the transport of batman-adv packets. If you experience"
349 " problems getting traffic through try increasing the "
350 "MTU to %zi.\n",
351 batman_if->net_dev->name, batman_if->net_dev->mtu,
352 ETH_DATA_LEN + BAT_HEADER_LEN);
353
354 if (hardif_is_iface_up(batman_if))
355 hardif_activate_interface(batman_if);
356 else
357 bat_err(batman_if->soft_iface, "Not using interface %s "
358 "(retrying later): interface not active\n",
359 batman_if->net_dev->name);
360
361 /* begin scheduling originator messages on that interface */
362 schedule_own_packet(batman_if);
363
364out:
365 return 0;
366
367err:
368 return -ENOMEM;
369}
370
371void hardif_disable_interface(struct batman_if *batman_if)
372{
373 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
374
375 if (batman_if->if_status == IF_ACTIVE)
376 hardif_deactivate_interface(batman_if);
377
378 if (batman_if->if_status != IF_INACTIVE)
379 return;
380
381 bat_info(batman_if->soft_iface, "Removing interface: %s\n",
382 batman_if->net_dev->name);
383 dev_remove_pack(&batman_if->batman_adv_ptype);
384 kref_put(&batman_if->refcount, hardif_free_ref);
385
386 bat_priv->num_ifaces--;
387 orig_hash_del_if(batman_if, bat_priv->num_ifaces);
388
389 if (batman_if == bat_priv->primary_if) {
390 struct batman_if *new_if;
391
392 new_if = get_active_batman_if(batman_if->soft_iface);
393 set_primary_if(bat_priv, new_if);
394
395 if (new_if)
396 kref_put(&new_if->refcount, hardif_free_ref);
397 }
398
399 kfree(batman_if->packet_buff);
400 batman_if->packet_buff = NULL;
401 batman_if->if_status = IF_NOT_IN_USE;
402
403 /* delete all references to this batman_if */
404 purge_orig_ref(bat_priv);
405 purge_outstanding_packets(bat_priv, batman_if);
406 dev_put(batman_if->soft_iface);
407
408 /* nobody uses this interface anymore */
409 if (!bat_priv->num_ifaces)
410 softif_destroy(batman_if->soft_iface);
411
412 batman_if->soft_iface = NULL;
413}
414
415static struct batman_if *hardif_add_interface(struct net_device *net_dev)
416{
417 struct batman_if *batman_if;
418 int ret;
419
420 ret = is_valid_iface(net_dev);
421 if (ret != 1)
422 goto out;
423
424 dev_hold(net_dev);
425
426 batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
427 if (!batman_if) {
428 pr_err("Can't add interface (%s): out of memory\n",
429 net_dev->name);
430 goto release_dev;
431 }
432
433 ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev);
434 if (ret)
435 goto free_if;
436
437 batman_if->if_num = -1;
438 batman_if->net_dev = net_dev;
439 batman_if->soft_iface = NULL;
440 batman_if->if_status = IF_NOT_IN_USE;
441 INIT_LIST_HEAD(&batman_if->list);
442 kref_init(&batman_if->refcount);
443
444 check_known_mac_addr(batman_if->net_dev);
445
446 spin_lock(&if_list_lock);
447 list_add_tail_rcu(&batman_if->list, &if_list);
448 spin_unlock(&if_list_lock);
449
450 /* extra reference for return */
451 kref_get(&batman_if->refcount);
452 return batman_if;
453
454free_if:
455 kfree(batman_if);
456release_dev:
457 dev_put(net_dev);
458out:
459 return NULL;
460}
461
462static void hardif_remove_interface(struct batman_if *batman_if)
463{
464 /* first deactivate interface */
465 if (batman_if->if_status != IF_NOT_IN_USE)
466 hardif_disable_interface(batman_if);
467
468 if (batman_if->if_status != IF_NOT_IN_USE)
469 return;
470
471 batman_if->if_status = IF_TO_BE_REMOVED;
472 synchronize_rcu();
473 sysfs_del_hardif(&batman_if->hardif_obj);
474 call_rcu(&batman_if->rcu, hardif_free_rcu);
475}
476
477void hardif_remove_interfaces(void)
478{
479 struct batman_if *batman_if, *batman_if_tmp;
480 struct list_head if_queue;
481
482 INIT_LIST_HEAD(&if_queue);
483
484 spin_lock(&if_list_lock);
485 list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) {
486 list_del_rcu(&batman_if->list);
487 list_add_tail(&batman_if->list, &if_queue);
488 }
489 spin_unlock(&if_list_lock);
490
491 rtnl_lock();
492 list_for_each_entry_safe(batman_if, batman_if_tmp, &if_queue, list) {
493 hardif_remove_interface(batman_if);
494 }
495 rtnl_unlock();
496}
497
498static int hard_if_event(struct notifier_block *this,
499 unsigned long event, void *ptr)
500{
501 struct net_device *net_dev = (struct net_device *)ptr;
502 struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
503 struct bat_priv *bat_priv;
504
505 if (!batman_if && event == NETDEV_REGISTER)
506 batman_if = hardif_add_interface(net_dev);
507
508 if (!batman_if)
509 goto out;
510
511 switch (event) {
512 case NETDEV_UP:
513 hardif_activate_interface(batman_if);
514 break;
515 case NETDEV_GOING_DOWN:
516 case NETDEV_DOWN:
517 hardif_deactivate_interface(batman_if);
518 break;
519 case NETDEV_UNREGISTER:
520 spin_lock(&if_list_lock);
521 list_del_rcu(&batman_if->list);
522 spin_unlock(&if_list_lock);
523
524 hardif_remove_interface(batman_if);
525 break;
526 case NETDEV_CHANGEMTU:
527 if (batman_if->soft_iface)
528 update_min_mtu(batman_if->soft_iface);
529 break;
530 case NETDEV_CHANGEADDR:
531 if (batman_if->if_status == IF_NOT_IN_USE)
532 goto hardif_put;
533
534 check_known_mac_addr(batman_if->net_dev);
535 update_mac_addresses(batman_if);
536
537 bat_priv = netdev_priv(batman_if->soft_iface);
538 if (batman_if == bat_priv->primary_if)
539 update_primary_addr(bat_priv);
540 break;
541 default:
542 break;
543 };
544
545hardif_put:
546 kref_put(&batman_if->refcount, hardif_free_ref);
547out:
548 return NOTIFY_DONE;
549}
550
551/* receive a packet with the batman ethertype coming on a hard
552 * interface */
553int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
554 struct packet_type *ptype, struct net_device *orig_dev)
555{
556 struct bat_priv *bat_priv;
557 struct batman_packet *batman_packet;
558 struct batman_if *batman_if;
559 int ret;
560
561 batman_if = container_of(ptype, struct batman_if, batman_adv_ptype);
562 skb = skb_share_check(skb, GFP_ATOMIC);
563
564 /* skb was released by skb_share_check() */
565 if (!skb)
566 goto err_out;
567
568 /* packet should hold at least type and version */
569 if (unlikely(!pskb_may_pull(skb, 2)))
570 goto err_free;
571
572 /* expect a valid ethernet header here. */
573 if (unlikely(skb->mac_len != sizeof(struct ethhdr)
574 || !skb_mac_header(skb)))
575 goto err_free;
576
577 if (!batman_if->soft_iface)
578 goto err_free;
579
580 bat_priv = netdev_priv(batman_if->soft_iface);
581
582 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
583 goto err_free;
584
585 /* discard frames on not active interfaces */
586 if (batman_if->if_status != IF_ACTIVE)
587 goto err_free;
588
589 batman_packet = (struct batman_packet *)skb->data;
590
591 if (batman_packet->version != COMPAT_VERSION) {
592 bat_dbg(DBG_BATMAN, bat_priv,
593 "Drop packet: incompatible batman version (%i)\n",
594 batman_packet->version);
595 goto err_free;
596 }
597
598 /* all receive handlers return whether they received or reused
599 * the supplied skb. if not, we have to free the skb. */
600
601 switch (batman_packet->packet_type) {
602 /* batman originator packet */
603 case BAT_PACKET:
604 ret = recv_bat_packet(skb, batman_if);
605 break;
606
607 /* batman icmp packet */
608 case BAT_ICMP:
609 ret = recv_icmp_packet(skb, batman_if);
610 break;
611
612 /* unicast packet */
613 case BAT_UNICAST:
614 ret = recv_unicast_packet(skb, batman_if);
615 break;
616
617 /* fragmented unicast packet */
618 case BAT_UNICAST_FRAG:
619 ret = recv_ucast_frag_packet(skb, batman_if);
620 break;
621
622 /* broadcast packet */
623 case BAT_BCAST:
624 ret = recv_bcast_packet(skb, batman_if);
625 break;
626
627 /* vis packet */
628 case BAT_VIS:
629 ret = recv_vis_packet(skb, batman_if);
630 break;
631 default:
632 ret = NET_RX_DROP;
633 }
634
635 if (ret == NET_RX_DROP)
636 kfree_skb(skb);
637
638 /* return NET_RX_SUCCESS in any case as we
639 * most probably dropped the packet for
640 * routing-logical reasons. */
641
642 return NET_RX_SUCCESS;
643
644err_free:
645 kfree_skb(skb);
646err_out:
647 return NET_RX_DROP;
648}
649
650struct notifier_block hard_if_notifier = {
651 .notifier_call = hard_if_event,
652};
diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h
deleted file mode 100644
index 30ec3b8db459..000000000000
--- a/drivers/staging/batman-adv/hard-interface.h
+++ /dev/null
@@ -1,53 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_HARD_INTERFACE_H_
23#define _NET_BATMAN_ADV_HARD_INTERFACE_H_
24
25#define IF_NOT_IN_USE 0
26#define IF_TO_BE_REMOVED 1
27#define IF_INACTIVE 2
28#define IF_ACTIVE 3
29#define IF_TO_BE_ACTIVATED 4
30#define IF_I_WANT_YOU 5
31
32extern struct notifier_block hard_if_notifier;
33
34struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev);
35int hardif_enable_interface(struct batman_if *batman_if, char *iface_name);
36void hardif_disable_interface(struct batman_if *batman_if);
37void hardif_remove_interfaces(void);
38int batman_skb_recv(struct sk_buff *skb,
39 struct net_device *dev,
40 struct packet_type *ptype,
41 struct net_device *orig_dev);
42int hardif_min_mtu(struct net_device *soft_iface);
43void update_min_mtu(struct net_device *soft_iface);
44
45static inline void hardif_free_ref(struct kref *refcount)
46{
47 struct batman_if *batman_if;
48
49 batman_if = container_of(refcount, struct batman_if, refcount);
50 kfree(batman_if);
51}
52
53#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c
deleted file mode 100644
index 8605e2fd0427..000000000000
--- a/drivers/staging/batman-adv/hash.c
+++ /dev/null
@@ -1,83 +0,0 @@
1/*
2 * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich, Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "hash.h"
24
25/* clears the hash */
26static void hash_init(struct hashtable_t *hash)
27{
28 int i;
29
30 hash->elements = 0;
31
32 for (i = 0 ; i < hash->size; i++)
33 INIT_HLIST_HEAD(&hash->table[i]);
34}
35
36/* free only the hashtable and the hash itself. */
37void hash_destroy(struct hashtable_t *hash)
38{
39 kfree(hash->table);
40 kfree(hash);
41}
42
43/* allocates and clears the hash */
44struct hashtable_t *hash_new(int size)
45{
46 struct hashtable_t *hash;
47
48 hash = kmalloc(sizeof(struct hashtable_t) , GFP_ATOMIC);
49
50 if (hash == NULL)
51 return NULL;
52
53 hash->size = size;
54 hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC);
55
56 if (hash->table == NULL) {
57 kfree(hash);
58 return NULL;
59 }
60
61 hash_init(hash);
62
63 return hash;
64}
65
66/* remove bucket (this might be used in hash_iterate() if you already found the
67 * bucket you want to delete and don't need the overhead to find it again with
68 * hash_remove(). But usually, you don't want to use this function, as it
69 * fiddles with hash-internals. */
70void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t)
71{
72 void *data_save;
73 struct element_t *bucket;
74
75 bucket = hlist_entry(hash_it_t->walk, struct element_t, hlist);
76 data_save = bucket->data;
77
78 hlist_del(hash_it_t->walk);
79 kfree(bucket);
80 hash->elements--;
81
82 return data_save;
83}
diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h
deleted file mode 100644
index 0b61c6e3e7cf..000000000000
--- a/drivers/staging/batman-adv/hash.h
+++ /dev/null
@@ -1,259 +0,0 @@
1/*
2 * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich, Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_HASH_H_
23#define _NET_BATMAN_ADV_HASH_H_
24
25#include <linux/list.h>
26
27#define HASHIT(name) struct hash_it_t name = { \
28 .index = 0, .walk = NULL, \
29 .safe = NULL}
30
31/* callback to a compare function. should
32 * compare 2 element datas for their keys,
33 * return 0 if same and not 0 if not
34 * same */
35typedef int (*hashdata_compare_cb)(void *, void *);
36
37/* the hashfunction, should return an index
38 * based on the key in the data of the first
39 * argument and the size the second */
40typedef int (*hashdata_choose_cb)(void *, int);
41typedef void (*hashdata_free_cb)(void *, void *);
42
43struct element_t {
44 void *data; /* pointer to the data */
45 struct hlist_node hlist; /* bucket list pointer */
46};
47
48struct hash_it_t {
49 size_t index;
50 struct hlist_node *walk;
51 struct hlist_node *safe;
52};
53
54struct hashtable_t {
55 struct hlist_head *table; /* the hashtable itself, with the buckets */
56 int elements; /* number of elements registered */
57 int size; /* size of hashtable */
58};
59
60/* allocates and clears the hash */
61struct hashtable_t *hash_new(int size);
62
63/* remove bucket (this might be used in hash_iterate() if you already found the
64 * bucket you want to delete and don't need the overhead to find it again with
65 * hash_remove(). But usually, you don't want to use this function, as it
66 * fiddles with hash-internals. */
67void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t);
68
69/* free only the hashtable and the hash itself. */
70void hash_destroy(struct hashtable_t *hash);
71
72/* remove the hash structure. if hashdata_free_cb != NULL, this function will be
73 * called to remove the elements inside of the hash. if you don't remove the
74 * elements, memory might be leaked. */
75static inline void hash_delete(struct hashtable_t *hash,
76 hashdata_free_cb free_cb, void *arg)
77{
78 struct hlist_head *head;
79 struct hlist_node *walk, *safe;
80 struct element_t *bucket;
81 int i;
82
83 for (i = 0; i < hash->size; i++) {
84 head = &hash->table[i];
85
86 hlist_for_each_safe(walk, safe, head) {
87 bucket = hlist_entry(walk, struct element_t, hlist);
88 if (free_cb != NULL)
89 free_cb(bucket->data, arg);
90
91 hlist_del(walk);
92 kfree(bucket);
93 }
94 }
95
96 hash_destroy(hash);
97}
98
99/* adds data to the hashtable. returns 0 on success, -1 on error */
100static inline int hash_add(struct hashtable_t *hash,
101 hashdata_compare_cb compare,
102 hashdata_choose_cb choose, void *data)
103{
104 int index;
105 struct hlist_head *head;
106 struct hlist_node *walk, *safe;
107 struct element_t *bucket;
108
109 if (!hash)
110 return -1;
111
112 index = choose(data, hash->size);
113 head = &hash->table[index];
114
115 hlist_for_each_safe(walk, safe, head) {
116 bucket = hlist_entry(walk, struct element_t, hlist);
117 if (compare(bucket->data, data))
118 return -1;
119 }
120
121 /* no duplicate found in list, add new element */
122 bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC);
123
124 if (bucket == NULL)
125 return -1;
126
127 bucket->data = data;
128 hlist_add_head(&bucket->hlist, head);
129
130 hash->elements++;
131 return 0;
132}
133
134/* removes data from hash, if found. returns pointer do data on success, so you
135 * can remove the used structure yourself, or NULL on error . data could be the
136 * structure you use with just the key filled, we just need the key for
137 * comparing. */
138static inline void *hash_remove(struct hashtable_t *hash,
139 hashdata_compare_cb compare,
140 hashdata_choose_cb choose, void *data)
141{
142 struct hash_it_t hash_it_t;
143 struct element_t *bucket;
144 struct hlist_head *head;
145
146 hash_it_t.index = choose(data, hash->size);
147 head = &hash->table[hash_it_t.index];
148
149 hlist_for_each(hash_it_t.walk, head) {
150 bucket = hlist_entry(hash_it_t.walk, struct element_t, hlist);
151 if (compare(bucket->data, data))
152 return hash_remove_bucket(hash, &hash_it_t);
153 }
154
155 return NULL;
156}
157
158/* finds data, based on the key in keydata. returns the found data on success,
159 * or NULL on error */
160static inline void *hash_find(struct hashtable_t *hash,
161 hashdata_compare_cb compare,
162 hashdata_choose_cb choose, void *keydata)
163{
164 int index;
165 struct hlist_head *head;
166 struct hlist_node *walk;
167 struct element_t *bucket;
168
169 if (!hash)
170 return NULL;
171
172 index = choose(keydata , hash->size);
173 head = &hash->table[index];
174
175 hlist_for_each(walk, head) {
176 bucket = hlist_entry(walk, struct element_t, hlist);
177 if (compare(bucket->data, keydata))
178 return bucket->data;
179 }
180
181 return NULL;
182}
183
184/* resize the hash, returns the pointer to the new hash or NULL on
185 * error. removes the old hash on success */
186static inline struct hashtable_t *hash_resize(struct hashtable_t *hash,
187 hashdata_choose_cb choose,
188 int size)
189{
190 struct hashtable_t *new_hash;
191 struct hlist_head *head, *new_head;
192 struct hlist_node *walk, *safe;
193 struct element_t *bucket;
194 int i, new_index;
195
196 /* initialize a new hash with the new size */
197 new_hash = hash_new(size);
198
199 if (new_hash == NULL)
200 return NULL;
201
202 /* copy the elements */
203 for (i = 0; i < hash->size; i++) {
204 head = &hash->table[i];
205
206 hlist_for_each_safe(walk, safe, head) {
207 bucket = hlist_entry(walk, struct element_t, hlist);
208
209 new_index = choose(bucket->data, size);
210 new_head = &new_hash->table[new_index];
211
212 hlist_del(walk);
213 hlist_add_head(walk, new_head);
214 }
215 }
216
217 hash_destroy(hash);
218
219 return new_hash;
220}
221
222/* iterate though the hash. First element is selected if an iterator
223 * initialized with HASHIT() is supplied as iter. Use the returned
224 * (or supplied) iterator to access the elements until hash_iterate returns
225 * NULL. */
226static inline struct hash_it_t *hash_iterate(struct hashtable_t *hash,
227 struct hash_it_t *iter)
228{
229 if (!hash)
230 return NULL;
231 if (!iter)
232 return NULL;
233
234 iter->walk = iter->safe;
235
236 /* we search for the next head with list entries */
237 if (!iter->walk) {
238 while (iter->index < hash->size) {
239 if (hlist_empty(&hash->table[iter->index]))
240 iter->index++;
241 else {
242 iter->walk = hash->table[iter->index].first;
243
244 /* search next time */
245 ++iter->index;
246 break;
247 }
248 }
249 }
250
251 /* return iter when we found bucket otherwise null */
252 if (!iter->walk)
253 return NULL;
254
255 iter->safe = iter->walk->next;
256 return iter;
257}
258
259#endif /* _NET_BATMAN_ADV_HASH_H_ */
diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c
deleted file mode 100644
index a933ca609b74..000000000000
--- a/drivers/staging/batman-adv/icmp_socket.c
+++ /dev/null
@@ -1,357 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include <linux/debugfs.h>
24#include <linux/slab.h>
25#include "icmp_socket.h"
26#include "send.h"
27#include "types.h"
28#include "hash.h"
29#include "originator.h"
30#include "hard-interface.h"
31
32
33static struct socket_client *socket_client_hash[256];
34
35static void bat_socket_add_packet(struct socket_client *socket_client,
36 struct icmp_packet_rr *icmp_packet,
37 size_t icmp_len);
38
39void bat_socket_init(void)
40{
41 memset(socket_client_hash, 0, sizeof(socket_client_hash));
42}
43
44static int bat_socket_open(struct inode *inode, struct file *file)
45{
46 unsigned int i;
47 struct socket_client *socket_client;
48
49 nonseekable_open(inode, file);
50
51 socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL);
52
53 if (!socket_client)
54 return -ENOMEM;
55
56 for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) {
57 if (!socket_client_hash[i]) {
58 socket_client_hash[i] = socket_client;
59 break;
60 }
61 }
62
63 if (i == ARRAY_SIZE(socket_client_hash)) {
64 pr_err("Error - can't add another packet client: "
65 "maximum number of clients reached\n");
66 kfree(socket_client);
67 return -EXFULL;
68 }
69
70 INIT_LIST_HEAD(&socket_client->queue_list);
71 socket_client->queue_len = 0;
72 socket_client->index = i;
73 socket_client->bat_priv = inode->i_private;
74 spin_lock_init(&socket_client->lock);
75 init_waitqueue_head(&socket_client->queue_wait);
76
77 file->private_data = socket_client;
78
79 inc_module_count();
80 return 0;
81}
82
83static int bat_socket_release(struct inode *inode, struct file *file)
84{
85 struct socket_client *socket_client = file->private_data;
86 struct socket_packet *socket_packet;
87 struct list_head *list_pos, *list_pos_tmp;
88
89 spin_lock_bh(&socket_client->lock);
90
91 /* for all packets in the queue ... */
92 list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) {
93 socket_packet = list_entry(list_pos,
94 struct socket_packet, list);
95
96 list_del(list_pos);
97 kfree(socket_packet);
98 }
99
100 socket_client_hash[socket_client->index] = NULL;
101 spin_unlock_bh(&socket_client->lock);
102
103 kfree(socket_client);
104 dec_module_count();
105
106 return 0;
107}
108
109static ssize_t bat_socket_read(struct file *file, char __user *buf,
110 size_t count, loff_t *ppos)
111{
112 struct socket_client *socket_client = file->private_data;
113 struct socket_packet *socket_packet;
114 size_t packet_len;
115 int error;
116
117 if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0))
118 return -EAGAIN;
119
120 if ((!buf) || (count < sizeof(struct icmp_packet)))
121 return -EINVAL;
122
123 if (!access_ok(VERIFY_WRITE, buf, count))
124 return -EFAULT;
125
126 error = wait_event_interruptible(socket_client->queue_wait,
127 socket_client->queue_len);
128
129 if (error)
130 return error;
131
132 spin_lock_bh(&socket_client->lock);
133
134 socket_packet = list_first_entry(&socket_client->queue_list,
135 struct socket_packet, list);
136 list_del(&socket_packet->list);
137 socket_client->queue_len--;
138
139 spin_unlock_bh(&socket_client->lock);
140
141 error = __copy_to_user(buf, &socket_packet->icmp_packet,
142 socket_packet->icmp_len);
143
144 packet_len = socket_packet->icmp_len;
145 kfree(socket_packet);
146
147 if (error)
148 return -EFAULT;
149
150 return packet_len;
151}
152
153static ssize_t bat_socket_write(struct file *file, const char __user *buff,
154 size_t len, loff_t *off)
155{
156 struct socket_client *socket_client = file->private_data;
157 struct bat_priv *bat_priv = socket_client->bat_priv;
158 struct sk_buff *skb;
159 struct icmp_packet_rr *icmp_packet;
160
161 struct orig_node *orig_node;
162 struct batman_if *batman_if;
163 size_t packet_len = sizeof(struct icmp_packet);
164 uint8_t dstaddr[ETH_ALEN];
165
166 if (len < sizeof(struct icmp_packet)) {
167 bat_dbg(DBG_BATMAN, bat_priv,
168 "Error - can't send packet from char device: "
169 "invalid packet size\n");
170 return -EINVAL;
171 }
172
173 if (!bat_priv->primary_if)
174 return -EFAULT;
175
176 if (len >= sizeof(struct icmp_packet_rr))
177 packet_len = sizeof(struct icmp_packet_rr);
178
179 skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
180 if (!skb)
181 return -ENOMEM;
182
183 skb_reserve(skb, sizeof(struct ethhdr));
184 icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
185
186 if (!access_ok(VERIFY_READ, buff, packet_len)) {
187 len = -EFAULT;
188 goto free_skb;
189 }
190
191 if (__copy_from_user(icmp_packet, buff, packet_len)) {
192 len = -EFAULT;
193 goto free_skb;
194 }
195
196 if (icmp_packet->packet_type != BAT_ICMP) {
197 bat_dbg(DBG_BATMAN, bat_priv,
198 "Error - can't send packet from char device: "
199 "got bogus packet type (expected: BAT_ICMP)\n");
200 len = -EINVAL;
201 goto free_skb;
202 }
203
204 if (icmp_packet->msg_type != ECHO_REQUEST) {
205 bat_dbg(DBG_BATMAN, bat_priv,
206 "Error - can't send packet from char device: "
207 "got bogus message type (expected: ECHO_REQUEST)\n");
208 len = -EINVAL;
209 goto free_skb;
210 }
211
212 icmp_packet->uid = socket_client->index;
213
214 if (icmp_packet->version != COMPAT_VERSION) {
215 icmp_packet->msg_type = PARAMETER_PROBLEM;
216 icmp_packet->ttl = COMPAT_VERSION;
217 bat_socket_add_packet(socket_client, icmp_packet, packet_len);
218 goto free_skb;
219 }
220
221 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
222 goto dst_unreach;
223
224 spin_lock_bh(&bat_priv->orig_hash_lock);
225 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
226 compare_orig, choose_orig,
227 icmp_packet->dst));
228
229 if (!orig_node)
230 goto unlock;
231
232 if (!orig_node->router)
233 goto unlock;
234
235 batman_if = orig_node->router->if_incoming;
236 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
237
238 spin_unlock_bh(&bat_priv->orig_hash_lock);
239
240 if (!batman_if)
241 goto dst_unreach;
242
243 if (batman_if->if_status != IF_ACTIVE)
244 goto dst_unreach;
245
246 memcpy(icmp_packet->orig,
247 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
248
249 if (packet_len == sizeof(struct icmp_packet_rr))
250 memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN);
251
252
253 send_skb_packet(skb, batman_if, dstaddr);
254
255 goto out;
256
257unlock:
258 spin_unlock_bh(&bat_priv->orig_hash_lock);
259dst_unreach:
260 icmp_packet->msg_type = DESTINATION_UNREACHABLE;
261 bat_socket_add_packet(socket_client, icmp_packet, packet_len);
262free_skb:
263 kfree_skb(skb);
264out:
265 return len;
266}
267
268static unsigned int bat_socket_poll(struct file *file, poll_table *wait)
269{
270 struct socket_client *socket_client = file->private_data;
271
272 poll_wait(file, &socket_client->queue_wait, wait);
273
274 if (socket_client->queue_len > 0)
275 return POLLIN | POLLRDNORM;
276
277 return 0;
278}
279
280static const struct file_operations fops = {
281 .owner = THIS_MODULE,
282 .open = bat_socket_open,
283 .release = bat_socket_release,
284 .read = bat_socket_read,
285 .write = bat_socket_write,
286 .poll = bat_socket_poll,
287 .llseek = no_llseek,
288};
289
290int bat_socket_setup(struct bat_priv *bat_priv)
291{
292 struct dentry *d;
293
294 if (!bat_priv->debug_dir)
295 goto err;
296
297 d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
298 bat_priv->debug_dir, bat_priv, &fops);
299 if (d)
300 goto err;
301
302 return 0;
303
304err:
305 return 1;
306}
307
308static void bat_socket_add_packet(struct socket_client *socket_client,
309 struct icmp_packet_rr *icmp_packet,
310 size_t icmp_len)
311{
312 struct socket_packet *socket_packet;
313
314 socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC);
315
316 if (!socket_packet)
317 return;
318
319 INIT_LIST_HEAD(&socket_packet->list);
320 memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len);
321 socket_packet->icmp_len = icmp_len;
322
323 spin_lock_bh(&socket_client->lock);
324
325 /* while waiting for the lock the socket_client could have been
326 * deleted */
327 if (!socket_client_hash[icmp_packet->uid]) {
328 spin_unlock_bh(&socket_client->lock);
329 kfree(socket_packet);
330 return;
331 }
332
333 list_add_tail(&socket_packet->list, &socket_client->queue_list);
334 socket_client->queue_len++;
335
336 if (socket_client->queue_len > 100) {
337 socket_packet = list_first_entry(&socket_client->queue_list,
338 struct socket_packet, list);
339
340 list_del(&socket_packet->list);
341 kfree(socket_packet);
342 socket_client->queue_len--;
343 }
344
345 spin_unlock_bh(&socket_client->lock);
346
347 wake_up(&socket_client->queue_wait);
348}
349
350void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet,
351 size_t icmp_len)
352{
353 struct socket_client *hash = socket_client_hash[icmp_packet->uid];
354
355 if (hash)
356 bat_socket_add_packet(hash, icmp_packet, icmp_len);
357}
diff --git a/drivers/staging/batman-adv/icmp_socket.h b/drivers/staging/batman-adv/icmp_socket.h
deleted file mode 100644
index bf9b348cde27..000000000000
--- a/drivers/staging/batman-adv/icmp_socket.h
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_ICMP_SOCKET_H_
23#define _NET_BATMAN_ADV_ICMP_SOCKET_H_
24
25#include "types.h"
26
27#define ICMP_SOCKET "socket"
28
29void bat_socket_init(void);
30int bat_socket_setup(struct bat_priv *bat_priv);
31void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet,
32 size_t icmp_len);
33
34#endif /* _NET_BATMAN_ADV_ICMP_SOCKET_H_ */
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
deleted file mode 100644
index b827f6a158cb..000000000000
--- a/drivers/staging/batman-adv/main.c
+++ /dev/null
@@ -1,187 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "bat_sysfs.h"
24#include "bat_debugfs.h"
25#include "routing.h"
26#include "send.h"
27#include "originator.h"
28#include "soft-interface.h"
29#include "icmp_socket.h"
30#include "translation-table.h"
31#include "hard-interface.h"
32#include "gateway_client.h"
33#include "types.h"
34#include "vis.h"
35#include "hash.h"
36
37struct list_head if_list;
38
39unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
40
41struct workqueue_struct *bat_event_workqueue;
42
43static int __init batman_init(void)
44{
45 INIT_LIST_HEAD(&if_list);
46
47 /* the name should not be longer than 10 chars - see
48 * http://lwn.net/Articles/23634/ */
49 bat_event_workqueue = create_singlethread_workqueue("bat_events");
50
51 if (!bat_event_workqueue)
52 return -ENOMEM;
53
54 bat_socket_init();
55 debugfs_init();
56
57 register_netdevice_notifier(&hard_if_notifier);
58
59 pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) "
60 "loaded\n", SOURCE_VERSION, REVISION_VERSION_STR,
61 COMPAT_VERSION);
62
63 return 0;
64}
65
66static void __exit batman_exit(void)
67{
68 debugfs_destroy();
69 unregister_netdevice_notifier(&hard_if_notifier);
70 hardif_remove_interfaces();
71
72 flush_workqueue(bat_event_workqueue);
73 destroy_workqueue(bat_event_workqueue);
74 bat_event_workqueue = NULL;
75
76 rcu_barrier();
77}
78
79int mesh_init(struct net_device *soft_iface)
80{
81 struct bat_priv *bat_priv = netdev_priv(soft_iface);
82
83 spin_lock_init(&bat_priv->orig_hash_lock);
84 spin_lock_init(&bat_priv->forw_bat_list_lock);
85 spin_lock_init(&bat_priv->forw_bcast_list_lock);
86 spin_lock_init(&bat_priv->hna_lhash_lock);
87 spin_lock_init(&bat_priv->hna_ghash_lock);
88 spin_lock_init(&bat_priv->gw_list_lock);
89 spin_lock_init(&bat_priv->vis_hash_lock);
90 spin_lock_init(&bat_priv->vis_list_lock);
91 spin_lock_init(&bat_priv->softif_neigh_lock);
92
93 INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
94 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
95 INIT_HLIST_HEAD(&bat_priv->gw_list);
96 INIT_HLIST_HEAD(&bat_priv->softif_neigh_list);
97
98 if (originator_init(bat_priv) < 1)
99 goto err;
100
101 if (hna_local_init(bat_priv) < 1)
102 goto err;
103
104 if (hna_global_init(bat_priv) < 1)
105 goto err;
106
107 hna_local_add(soft_iface, soft_iface->dev_addr);
108
109 if (vis_init(bat_priv) < 1)
110 goto err;
111
112 atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
113 goto end;
114
115err:
116 pr_err("Unable to allocate memory for mesh information structures: "
117 "out of mem ?\n");
118 mesh_free(soft_iface);
119 return -1;
120
121end:
122 return 0;
123}
124
125void mesh_free(struct net_device *soft_iface)
126{
127 struct bat_priv *bat_priv = netdev_priv(soft_iface);
128
129 atomic_set(&bat_priv->mesh_state, MESH_DEACTIVATING);
130
131 purge_outstanding_packets(bat_priv, NULL);
132
133 vis_quit(bat_priv);
134
135 gw_node_purge(bat_priv);
136 originator_free(bat_priv);
137
138 hna_local_free(bat_priv);
139 hna_global_free(bat_priv);
140
141 softif_neigh_purge(bat_priv);
142
143 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
144}
145
146void inc_module_count(void)
147{
148 try_module_get(THIS_MODULE);
149}
150
151void dec_module_count(void)
152{
153 module_put(THIS_MODULE);
154}
155
156int is_my_mac(uint8_t *addr)
157{
158 struct batman_if *batman_if;
159
160 rcu_read_lock();
161 list_for_each_entry_rcu(batman_if, &if_list, list) {
162 if (batman_if->if_status != IF_ACTIVE)
163 continue;
164
165 if (compare_orig(batman_if->net_dev->dev_addr, addr)) {
166 rcu_read_unlock();
167 return 1;
168 }
169 }
170 rcu_read_unlock();
171 return 0;
172
173}
174
175module_init(batman_init);
176module_exit(batman_exit);
177
178MODULE_LICENSE("GPL");
179
180MODULE_AUTHOR(DRIVER_AUTHOR);
181MODULE_DESCRIPTION(DRIVER_DESC);
182MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
183#ifdef REVISION_VERSION
184MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
185#else
186MODULE_VERSION(SOURCE_VERSION);
187#endif
diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h
deleted file mode 100644
index 6b60c33a8b77..000000000000
--- a/drivers/staging/batman-adv/main.h
+++ /dev/null
@@ -1,180 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_MAIN_H_
23#define _NET_BATMAN_ADV_MAIN_H_
24
25/* Kernel Programming */
26#define LINUX
27
28#define DRIVER_AUTHOR "Marek Lindner <lindner_marek@yahoo.de>, " \
29 "Simon Wunderlich <siwu@hrz.tu-chemnitz.de>"
30#define DRIVER_DESC "B.A.T.M.A.N. advanced"
31#define DRIVER_DEVICE "batman-adv"
32
33#define SOURCE_VERSION "next"
34
35
36/* B.A.T.M.A.N. parameters */
37
38#define TQ_MAX_VALUE 255
39#define JITTER 20
40#define TTL 50 /* Time To Live of broadcast messages */
41
42#define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no
43 * valid packet comes in -> TODO: check
44 * influence on TQ_LOCAL_WINDOW_SIZE */
45#define LOCAL_HNA_TIMEOUT 3600 /* in seconds */
46
47#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
48 * messages in squence numbers (should be a
49 * multiple of our word size) */
50#define TQ_GLOBAL_WINDOW_SIZE 5
51#define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1
52#define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
53#define TQ_TOTAL_BIDRECT_LIMIT 1
54
55#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
56
57#define PACKBUFF_SIZE 2000
58#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
59
60#define VIS_INTERVAL 5000 /* 5 seconds */
61
62/* how much worse secondary interfaces may be to
63 * to be considered as bonding candidates */
64
65#define BONDING_TQ_THRESHOLD 50
66
67#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or
68 * change the size of
69 * forw_packet->direct_link_flags */
70#define MAX_AGGREGATION_MS 100
71
72#define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */
73
74#define RESET_PROTECTION_MS 30000
75#define EXPECTED_SEQNO_RANGE 65536
76/* don't reset again within 30 seconds */
77
78#define MESH_INACTIVE 0
79#define MESH_ACTIVE 1
80#define MESH_DEACTIVATING 2
81
82#define BCAST_QUEUE_LEN 256
83#define BATMAN_QUEUE_LEN 256
84
85/*
86 * Debug Messages
87 */
88#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before
89 * kernel messages */
90
91#define DBG_BATMAN 1 /* all messages related to routing / flooding /
92 * broadcasting / etc */
93#define DBG_ROUTES 2 /* route or hna added / changed / deleted */
94#define DBG_ALL 3
95
96#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
97
98
99/*
100 * Vis
101 */
102
103/* #define VIS_SUBCLUSTERS_DISABLED */
104
105/*
106 * Kernel headers
107 */
108
109#include <linux/mutex.h> /* mutex */
110#include <linux/module.h> /* needed by all modules */
111#include <linux/netdevice.h> /* netdevice */
112#include <linux/etherdevice.h> /* ethernet address classifaction */
113#include <linux/if_ether.h> /* ethernet header */
114#include <linux/poll.h> /* poll_table */
115#include <linux/kthread.h> /* kernel threads */
116#include <linux/pkt_sched.h> /* schedule types */
117#include <linux/workqueue.h> /* workqueue */
118#include <linux/slab.h>
119#include <net/sock.h> /* struct sock */
120#include <linux/jiffies.h>
121#include <linux/seq_file.h>
122#include "types.h"
123
124#ifndef REVISION_VERSION
125#define REVISION_VERSION_STR ""
126#else
127#define REVISION_VERSION_STR " "REVISION_VERSION
128#endif
129
130extern struct list_head if_list;
131
132extern unsigned char broadcast_addr[];
133extern struct workqueue_struct *bat_event_workqueue;
134
135int mesh_init(struct net_device *soft_iface);
136void mesh_free(struct net_device *soft_iface);
137void inc_module_count(void);
138void dec_module_count(void);
139int is_my_mac(uint8_t *addr);
140
141#ifdef CONFIG_BATMAN_ADV_DEBUG
142int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
143
144#define bat_dbg(type, bat_priv, fmt, arg...) \
145 do { \
146 if (atomic_read(&bat_priv->log_level) & type) \
147 debug_log(bat_priv, fmt, ## arg); \
148 } \
149 while (0)
150#else /* !CONFIG_BATMAN_ADV_DEBUG */
151static inline void bat_dbg(char type __attribute__((unused)),
152 struct bat_priv *bat_priv __attribute__((unused)),
153 char *fmt __attribute__((unused)), ...)
154{
155}
156#endif
157
158#define bat_warning(net_dev, fmt, arg...) \
159 do { \
160 struct net_device *_netdev = (net_dev); \
161 struct bat_priv *_batpriv = netdev_priv(_netdev); \
162 bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
163 pr_warning("%s: " fmt, _netdev->name, ## arg); \
164 } while (0)
165#define bat_info(net_dev, fmt, arg...) \
166 do { \
167 struct net_device *_netdev = (net_dev); \
168 struct bat_priv *_batpriv = netdev_priv(_netdev); \
169 bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
170 pr_info("%s: " fmt, _netdev->name, ## arg); \
171 } while (0)
172#define bat_err(net_dev, fmt, arg...) \
173 do { \
174 struct net_device *_netdev = (net_dev); \
175 struct bat_priv *_batpriv = netdev_priv(_netdev); \
176 bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
177 pr_err("%s: " fmt, _netdev->name, ## arg); \
178 } while (0)
179
180#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c
deleted file mode 100644
index 89ec02100a3b..000000000000
--- a/drivers/staging/batman-adv/originator.c
+++ /dev/null
@@ -1,546 +0,0 @@
1/*
2 * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22/* increase the reference counter for this originator */
23
24#include "main.h"
25#include "originator.h"
26#include "hash.h"
27#include "translation-table.h"
28#include "routing.h"
29#include "gateway_client.h"
30#include "hard-interface.h"
31#include "unicast.h"
32#include "soft-interface.h"
33
34static void purge_orig(struct work_struct *work);
35
36static void start_purge_timer(struct bat_priv *bat_priv)
37{
38 INIT_DELAYED_WORK(&bat_priv->orig_work, purge_orig);
39 queue_delayed_work(bat_event_workqueue, &bat_priv->orig_work, 1 * HZ);
40}
41
42int originator_init(struct bat_priv *bat_priv)
43{
44 if (bat_priv->orig_hash)
45 return 1;
46
47 spin_lock_bh(&bat_priv->orig_hash_lock);
48 bat_priv->orig_hash = hash_new(128);
49
50 if (!bat_priv->orig_hash)
51 goto err;
52
53 spin_unlock_bh(&bat_priv->orig_hash_lock);
54 start_purge_timer(bat_priv);
55 return 1;
56
57err:
58 spin_unlock_bh(&bat_priv->orig_hash_lock);
59 return 0;
60}
61
62struct neigh_node *
63create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
64 uint8_t *neigh, struct batman_if *if_incoming)
65{
66 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
67 struct neigh_node *neigh_node;
68
69 bat_dbg(DBG_BATMAN, bat_priv,
70 "Creating new last-hop neighbor of originator\n");
71
72 neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
73 if (!neigh_node)
74 return NULL;
75
76 INIT_LIST_HEAD(&neigh_node->list);
77
78 memcpy(neigh_node->addr, neigh, ETH_ALEN);
79 neigh_node->orig_node = orig_neigh_node;
80 neigh_node->if_incoming = if_incoming;
81
82 list_add_tail(&neigh_node->list, &orig_node->neigh_list);
83 return neigh_node;
84}
85
86static void free_orig_node(void *data, void *arg)
87{
88 struct list_head *list_pos, *list_pos_tmp;
89 struct neigh_node *neigh_node;
90 struct orig_node *orig_node = (struct orig_node *)data;
91 struct bat_priv *bat_priv = (struct bat_priv *)arg;
92
93 /* for all neighbors towards this originator ... */
94 list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
95 neigh_node = list_entry(list_pos, struct neigh_node, list);
96
97 list_del(list_pos);
98 kfree(neigh_node);
99 }
100
101 frag_list_free(&orig_node->frag_list);
102 hna_global_del_orig(bat_priv, orig_node, "originator timed out");
103
104 kfree(orig_node->bcast_own);
105 kfree(orig_node->bcast_own_sum);
106 kfree(orig_node);
107}
108
109void originator_free(struct bat_priv *bat_priv)
110{
111 if (!bat_priv->orig_hash)
112 return;
113
114 cancel_delayed_work_sync(&bat_priv->orig_work);
115
116 spin_lock_bh(&bat_priv->orig_hash_lock);
117 hash_delete(bat_priv->orig_hash, free_orig_node, bat_priv);
118 bat_priv->orig_hash = NULL;
119 spin_unlock_bh(&bat_priv->orig_hash_lock);
120}
121
122/* this function finds or creates an originator entry for the given
123 * address if it does not exits */
124struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
125{
126 struct orig_node *orig_node;
127 struct hashtable_t *swaphash;
128 int size;
129 int hash_added;
130
131 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
132 compare_orig, choose_orig,
133 addr));
134
135 if (orig_node)
136 return orig_node;
137
138 bat_dbg(DBG_BATMAN, bat_priv,
139 "Creating new originator: %pM\n", addr);
140
141 orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
142 if (!orig_node)
143 return NULL;
144
145 INIT_LIST_HEAD(&orig_node->neigh_list);
146
147 memcpy(orig_node->orig, addr, ETH_ALEN);
148 orig_node->router = NULL;
149 orig_node->hna_buff = NULL;
150 orig_node->bcast_seqno_reset = jiffies - 1
151 - msecs_to_jiffies(RESET_PROTECTION_MS);
152 orig_node->batman_seqno_reset = jiffies - 1
153 - msecs_to_jiffies(RESET_PROTECTION_MS);
154
155 size = bat_priv->num_ifaces * sizeof(TYPE_OF_WORD) * NUM_WORDS;
156
157 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
158 if (!orig_node->bcast_own)
159 goto free_orig_node;
160
161 size = bat_priv->num_ifaces * sizeof(uint8_t);
162 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
163
164 INIT_LIST_HEAD(&orig_node->frag_list);
165 orig_node->last_frag_packet = 0;
166
167 if (!orig_node->bcast_own_sum)
168 goto free_bcast_own;
169
170 hash_added = hash_add(bat_priv->orig_hash, compare_orig, choose_orig,
171 orig_node);
172 if (hash_added < 0)
173 goto free_bcast_own_sum;
174
175 if (bat_priv->orig_hash->elements * 4 > bat_priv->orig_hash->size) {
176 swaphash = hash_resize(bat_priv->orig_hash, choose_orig,
177 bat_priv->orig_hash->size * 2);
178
179 if (!swaphash)
180 bat_dbg(DBG_BATMAN, bat_priv,
181 "Couldn't resize orig hash table\n");
182 else
183 bat_priv->orig_hash = swaphash;
184 }
185
186 return orig_node;
187free_bcast_own_sum:
188 kfree(orig_node->bcast_own_sum);
189free_bcast_own:
190 kfree(orig_node->bcast_own);
191free_orig_node:
192 kfree(orig_node);
193 return NULL;
194}
195
196static bool purge_orig_neighbors(struct bat_priv *bat_priv,
197 struct orig_node *orig_node,
198 struct neigh_node **best_neigh_node)
199{
200 struct list_head *list_pos, *list_pos_tmp;
201 struct neigh_node *neigh_node;
202 bool neigh_purged = false;
203
204 *best_neigh_node = NULL;
205
206 /* for all neighbors towards this originator ... */
207 list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
208 neigh_node = list_entry(list_pos, struct neigh_node, list);
209
210 if ((time_after(jiffies,
211 neigh_node->last_valid + PURGE_TIMEOUT * HZ)) ||
212 (neigh_node->if_incoming->if_status == IF_INACTIVE) ||
213 (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
214
215 if (neigh_node->if_incoming->if_status ==
216 IF_TO_BE_REMOVED)
217 bat_dbg(DBG_BATMAN, bat_priv,
218 "neighbor purge: originator %pM, "
219 "neighbor: %pM, iface: %s\n",
220 orig_node->orig, neigh_node->addr,
221 neigh_node->if_incoming->net_dev->name);
222 else
223 bat_dbg(DBG_BATMAN, bat_priv,
224 "neighbor timeout: originator %pM, "
225 "neighbor: %pM, last_valid: %lu\n",
226 orig_node->orig, neigh_node->addr,
227 (neigh_node->last_valid / HZ));
228
229 neigh_purged = true;
230 list_del(list_pos);
231 kfree(neigh_node);
232 } else {
233 if ((*best_neigh_node == NULL) ||
234 (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
235 *best_neigh_node = neigh_node;
236 }
237 }
238 return neigh_purged;
239}
240
241static bool purge_orig_node(struct bat_priv *bat_priv,
242 struct orig_node *orig_node)
243{
244 struct neigh_node *best_neigh_node;
245
246 if (time_after(jiffies,
247 orig_node->last_valid + 2 * PURGE_TIMEOUT * HZ)) {
248
249 bat_dbg(DBG_BATMAN, bat_priv,
250 "Originator timeout: originator %pM, last_valid %lu\n",
251 orig_node->orig, (orig_node->last_valid / HZ));
252 return true;
253 } else {
254 if (purge_orig_neighbors(bat_priv, orig_node,
255 &best_neigh_node)) {
256 update_routes(bat_priv, orig_node,
257 best_neigh_node,
258 orig_node->hna_buff,
259 orig_node->hna_buff_len);
260 /* update bonding candidates, we could have lost
261 * some candidates. */
262 update_bonding_candidates(bat_priv, orig_node);
263 }
264 }
265
266 return false;
267}
268
269static void _purge_orig(struct bat_priv *bat_priv)
270{
271 HASHIT(hashit);
272 struct element_t *bucket;
273 struct orig_node *orig_node;
274
275 spin_lock_bh(&bat_priv->orig_hash_lock);
276
277 /* for all origins... */
278 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
279 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
280 orig_node = bucket->data;
281
282 if (purge_orig_node(bat_priv, orig_node)) {
283 if (orig_node->gw_flags)
284 gw_node_delete(bat_priv, orig_node);
285 hash_remove_bucket(bat_priv->orig_hash, &hashit);
286 free_orig_node(orig_node, bat_priv);
287 }
288
289 if (time_after(jiffies, (orig_node->last_frag_packet +
290 msecs_to_jiffies(FRAG_TIMEOUT))))
291 frag_list_free(&orig_node->frag_list);
292 }
293
294 spin_unlock_bh(&bat_priv->orig_hash_lock);
295
296 gw_node_purge(bat_priv);
297 gw_election(bat_priv);
298
299 softif_neigh_purge(bat_priv);
300}
301
302static void purge_orig(struct work_struct *work)
303{
304 struct delayed_work *delayed_work =
305 container_of(work, struct delayed_work, work);
306 struct bat_priv *bat_priv =
307 container_of(delayed_work, struct bat_priv, orig_work);
308
309 _purge_orig(bat_priv);
310 start_purge_timer(bat_priv);
311}
312
313void purge_orig_ref(struct bat_priv *bat_priv)
314{
315 _purge_orig(bat_priv);
316}
317
318int orig_seq_print_text(struct seq_file *seq, void *offset)
319{
320 HASHIT(hashit);
321 struct element_t *bucket;
322 struct net_device *net_dev = (struct net_device *)seq->private;
323 struct bat_priv *bat_priv = netdev_priv(net_dev);
324 struct orig_node *orig_node;
325 struct neigh_node *neigh_node;
326 int batman_count = 0;
327 int last_seen_secs;
328 int last_seen_msecs;
329
330 if ((!bat_priv->primary_if) ||
331 (bat_priv->primary_if->if_status != IF_ACTIVE)) {
332 if (!bat_priv->primary_if)
333 return seq_printf(seq, "BATMAN mesh %s disabled - "
334 "please specify interfaces to enable it\n",
335 net_dev->name);
336
337 return seq_printf(seq, "BATMAN mesh %s "
338 "disabled - primary interface not active\n",
339 net_dev->name);
340 }
341
342 seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
343 SOURCE_VERSION, REVISION_VERSION_STR,
344 bat_priv->primary_if->net_dev->name,
345 bat_priv->primary_if->net_dev->dev_addr, net_dev->name);
346 seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
347 "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
348 "outgoingIF", "Potential nexthops");
349
350 spin_lock_bh(&bat_priv->orig_hash_lock);
351
352 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
353 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
354 orig_node = bucket->data;
355
356 if (!orig_node->router)
357 continue;
358
359 if (orig_node->router->tq_avg == 0)
360 continue;
361
362 last_seen_secs = jiffies_to_msecs(jiffies -
363 orig_node->last_valid) / 1000;
364 last_seen_msecs = jiffies_to_msecs(jiffies -
365 orig_node->last_valid) % 1000;
366
367 seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:",
368 orig_node->orig, last_seen_secs, last_seen_msecs,
369 orig_node->router->tq_avg, orig_node->router->addr,
370 orig_node->router->if_incoming->net_dev->name);
371
372 list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
373 seq_printf(seq, " %pM (%3i)", neigh_node->addr,
374 neigh_node->tq_avg);
375 }
376
377 seq_printf(seq, "\n");
378 batman_count++;
379 }
380
381 spin_unlock_bh(&bat_priv->orig_hash_lock);
382
383 if ((batman_count == 0))
384 seq_printf(seq, "No batman nodes in range ...\n");
385
386 return 0;
387}
388
389static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
390{
391 void *data_ptr;
392
393 data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS,
394 GFP_ATOMIC);
395 if (!data_ptr) {
396 pr_err("Can't resize orig: out of memory\n");
397 return -1;
398 }
399
400 memcpy(data_ptr, orig_node->bcast_own,
401 (max_if_num - 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS);
402 kfree(orig_node->bcast_own);
403 orig_node->bcast_own = data_ptr;
404
405 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
406 if (!data_ptr) {
407 pr_err("Can't resize orig: out of memory\n");
408 return -1;
409 }
410
411 memcpy(data_ptr, orig_node->bcast_own_sum,
412 (max_if_num - 1) * sizeof(uint8_t));
413 kfree(orig_node->bcast_own_sum);
414 orig_node->bcast_own_sum = data_ptr;
415
416 return 0;
417}
418
419int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
420{
421 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
422 struct orig_node *orig_node;
423 HASHIT(hashit);
424 struct element_t *bucket;
425
426 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
427 * if_num */
428 spin_lock_bh(&bat_priv->orig_hash_lock);
429
430 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
431 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
432 orig_node = bucket->data;
433
434 if (orig_node_add_if(orig_node, max_if_num) == -1)
435 goto err;
436 }
437
438 spin_unlock_bh(&bat_priv->orig_hash_lock);
439 return 0;
440
441err:
442 spin_unlock_bh(&bat_priv->orig_hash_lock);
443 return -ENOMEM;
444}
445
446static int orig_node_del_if(struct orig_node *orig_node,
447 int max_if_num, int del_if_num)
448{
449 void *data_ptr = NULL;
450 int chunk_size;
451
452 /* last interface was removed */
453 if (max_if_num == 0)
454 goto free_bcast_own;
455
456 chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS;
457 data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
458 if (!data_ptr) {
459 pr_err("Can't resize orig: out of memory\n");
460 return -1;
461 }
462
463 /* copy first part */
464 memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
465
466 /* copy second part */
467 memcpy(data_ptr + del_if_num * chunk_size,
468 orig_node->bcast_own + ((del_if_num + 1) * chunk_size),
469 (max_if_num - del_if_num) * chunk_size);
470
471free_bcast_own:
472 kfree(orig_node->bcast_own);
473 orig_node->bcast_own = data_ptr;
474
475 if (max_if_num == 0)
476 goto free_own_sum;
477
478 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
479 if (!data_ptr) {
480 pr_err("Can't resize orig: out of memory\n");
481 return -1;
482 }
483
484 memcpy(data_ptr, orig_node->bcast_own_sum,
485 del_if_num * sizeof(uint8_t));
486
487 memcpy(data_ptr + del_if_num * sizeof(uint8_t),
488 orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)),
489 (max_if_num - del_if_num) * sizeof(uint8_t));
490
491free_own_sum:
492 kfree(orig_node->bcast_own_sum);
493 orig_node->bcast_own_sum = data_ptr;
494
495 return 0;
496}
497
498int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
499{
500 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
501 struct batman_if *batman_if_tmp;
502 struct orig_node *orig_node;
503 HASHIT(hashit);
504 struct element_t *bucket;
505 int ret;
506
507 /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
508 * if_num */
509 spin_lock_bh(&bat_priv->orig_hash_lock);
510
511 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
512 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
513 orig_node = bucket->data;
514
515 ret = orig_node_del_if(orig_node, max_if_num,
516 batman_if->if_num);
517
518 if (ret == -1)
519 goto err;
520 }
521
522 /* renumber remaining batman interfaces _inside_ of orig_hash_lock */
523 rcu_read_lock();
524 list_for_each_entry_rcu(batman_if_tmp, &if_list, list) {
525 if (batman_if_tmp->if_status == IF_NOT_IN_USE)
526 continue;
527
528 if (batman_if == batman_if_tmp)
529 continue;
530
531 if (batman_if->soft_iface != batman_if_tmp->soft_iface)
532 continue;
533
534 if (batman_if_tmp->if_num > batman_if->if_num)
535 batman_if_tmp->if_num--;
536 }
537 rcu_read_unlock();
538
539 batman_if->if_num = -1;
540 spin_unlock_bh(&bat_priv->orig_hash_lock);
541 return 0;
542
543err:
544 spin_unlock_bh(&bat_priv->orig_hash_lock);
545 return -ENOMEM;
546}
diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h
deleted file mode 100644
index d474ceb2a4eb..000000000000
--- a/drivers/staging/batman-adv/originator.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
23#define _NET_BATMAN_ADV_ORIGINATOR_H_
24
25int originator_init(struct bat_priv *bat_priv);
26void originator_free(struct bat_priv *bat_priv);
27void purge_orig_ref(struct bat_priv *bat_priv);
28struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
29struct neigh_node *
30create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
31 uint8_t *neigh, struct batman_if *if_incoming);
32int orig_seq_print_text(struct seq_file *seq, void *offset);
33int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
34int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
35
36
37/* returns 1 if they are the same originator */
38static inline int compare_orig(void *data1, void *data2)
39{
40 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
41}
42
43/* hashfunction to choose an entry in a hash table of given size */
44/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
45static inline int choose_orig(void *data, int32_t size)
46{
47 unsigned char *key = data;
48 uint32_t hash = 0;
49 size_t i;
50
51 for (i = 0; i < 6; i++) {
52 hash += key[i];
53 hash += (hash << 10);
54 hash ^= (hash >> 6);
55 }
56
57 hash += (hash << 3);
58 hash ^= (hash >> 11);
59 hash += (hash << 15);
60
61 return hash % size;
62}
63
64#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h
deleted file mode 100644
index b49fdf70a6d5..000000000000
--- a/drivers/staging/batman-adv/packet.h
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_PACKET_H_
23#define _NET_BATMAN_ADV_PACKET_H_
24
25#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
26
27#define BAT_PACKET 0x01
28#define BAT_ICMP 0x02
29#define BAT_UNICAST 0x03
30#define BAT_BCAST 0x04
31#define BAT_VIS 0x05
32#define BAT_UNICAST_FRAG 0x06
33
34/* this file is included by batctl which needs these defines */
35#define COMPAT_VERSION 12
36#define DIRECTLINK 0x40
37#define VIS_SERVER 0x20
38#define PRIMARIES_FIRST_HOP 0x10
39
40/* ICMP message types */
41#define ECHO_REPLY 0
42#define DESTINATION_UNREACHABLE 3
43#define ECHO_REQUEST 8
44#define TTL_EXCEEDED 11
45#define PARAMETER_PROBLEM 12
46
47/* vis defines */
48#define VIS_TYPE_SERVER_SYNC 0
49#define VIS_TYPE_CLIENT_UPDATE 1
50
51/* fragmentation defines */
52#define UNI_FRAG_HEAD 0x01
53
54struct batman_packet {
55 uint8_t packet_type;
56 uint8_t version; /* batman version field */
57 uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
58 uint8_t tq;
59 uint32_t seqno;
60 uint8_t orig[6];
61 uint8_t prev_sender[6];
62 uint8_t ttl;
63 uint8_t num_hna;
64 uint8_t gw_flags; /* flags related to gateway class */
65 uint8_t align;
66} __attribute__((packed));
67
68#define BAT_PACKET_LEN sizeof(struct batman_packet)
69
70struct icmp_packet {
71 uint8_t packet_type;
72 uint8_t version; /* batman version field */
73 uint8_t msg_type; /* see ICMP message types above */
74 uint8_t ttl;
75 uint8_t dst[6];
76 uint8_t orig[6];
77 uint16_t seqno;
78 uint8_t uid;
79} __attribute__((packed));
80
81#define BAT_RR_LEN 16
82
83/* icmp_packet_rr must start with all fields from imcp_packet
84 * as this is assumed by code that handles ICMP packets */
85struct icmp_packet_rr {
86 uint8_t packet_type;
87 uint8_t version; /* batman version field */
88 uint8_t msg_type; /* see ICMP message types above */
89 uint8_t ttl;
90 uint8_t dst[6];
91 uint8_t orig[6];
92 uint16_t seqno;
93 uint8_t uid;
94 uint8_t rr_cur;
95 uint8_t rr[BAT_RR_LEN][ETH_ALEN];
96} __attribute__((packed));
97
98struct unicast_packet {
99 uint8_t packet_type;
100 uint8_t version; /* batman version field */
101 uint8_t dest[6];
102 uint8_t ttl;
103} __attribute__((packed));
104
105struct unicast_frag_packet {
106 uint8_t packet_type;
107 uint8_t version; /* batman version field */
108 uint8_t dest[6];
109 uint8_t ttl;
110 uint8_t flags;
111 uint8_t orig[6];
112 uint16_t seqno;
113} __attribute__((packed));
114
115struct bcast_packet {
116 uint8_t packet_type;
117 uint8_t version; /* batman version field */
118 uint8_t orig[6];
119 uint8_t ttl;
120 uint32_t seqno;
121} __attribute__((packed));
122
123struct vis_packet {
124 uint8_t packet_type;
125 uint8_t version; /* batman version field */
126 uint8_t vis_type; /* which type of vis-participant sent this? */
127 uint8_t entries; /* number of entries behind this struct */
128 uint32_t seqno; /* sequence number */
129 uint8_t ttl; /* TTL */
130 uint8_t vis_orig[6]; /* originator that informs about its
131 * neighbors */
132 uint8_t target_orig[6]; /* who should receive this packet */
133 uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
134} __attribute__((packed));
135
136#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/drivers/staging/batman-adv/ring_buffer.c b/drivers/staging/batman-adv/ring_buffer.c
deleted file mode 100644
index defd37c9be1f..000000000000
--- a/drivers/staging/batman-adv/ring_buffer.c
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "ring_buffer.h"
24
25void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value)
26{
27 lq_recv[*lq_index] = value;
28 *lq_index = (*lq_index + 1) % TQ_GLOBAL_WINDOW_SIZE;
29}
30
31uint8_t ring_buffer_avg(uint8_t lq_recv[])
32{
33 uint8_t *ptr;
34 uint16_t count = 0, i = 0, sum = 0;
35
36 ptr = lq_recv;
37
38 while (i < TQ_GLOBAL_WINDOW_SIZE) {
39 if (*ptr != 0) {
40 count++;
41 sum += *ptr;
42 }
43
44 i++;
45 ptr++;
46 }
47
48 if (count == 0)
49 return 0;
50
51 return (uint8_t)(sum / count);
52}
diff --git a/drivers/staging/batman-adv/ring_buffer.h b/drivers/staging/batman-adv/ring_buffer.h
deleted file mode 100644
index 6b0cb9aaeba5..000000000000
--- a/drivers/staging/batman-adv/ring_buffer.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_RING_BUFFER_H_
23#define _NET_BATMAN_ADV_RING_BUFFER_H_
24
25void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
26uint8_t ring_buffer_avg(uint8_t lq_recv[]);
27
28#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
deleted file mode 100644
index d8b0c5a6d5df..000000000000
--- a/drivers/staging/batman-adv/routing.c
+++ /dev/null
@@ -1,1393 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "routing.h"
24#include "send.h"
25#include "hash.h"
26#include "soft-interface.h"
27#include "hard-interface.h"
28#include "icmp_socket.h"
29#include "translation-table.h"
30#include "originator.h"
31#include "types.h"
32#include "ring_buffer.h"
33#include "vis.h"
34#include "aggregation.h"
35#include "gateway_common.h"
36#include "gateway_client.h"
37#include "unicast.h"
38
39void slide_own_bcast_window(struct batman_if *batman_if)
40{
41 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
42 HASHIT(hashit);
43 struct element_t *bucket;
44 struct orig_node *orig_node;
45 TYPE_OF_WORD *word;
46
47 spin_lock_bh(&bat_priv->orig_hash_lock);
48
49 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
50 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
51 orig_node = bucket->data;
52 word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
53
54 bit_get_packet(bat_priv, word, 1, 0);
55 orig_node->bcast_own_sum[batman_if->if_num] =
56 bit_packet_count(word);
57 }
58
59 spin_unlock_bh(&bat_priv->orig_hash_lock);
60}
61
62static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node,
63 unsigned char *hna_buff, int hna_buff_len)
64{
65 if ((hna_buff_len != orig_node->hna_buff_len) ||
66 ((hna_buff_len > 0) &&
67 (orig_node->hna_buff_len > 0) &&
68 (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
69
70 if (orig_node->hna_buff_len > 0)
71 hna_global_del_orig(bat_priv, orig_node,
72 "originator changed hna");
73
74 if ((hna_buff_len > 0) && (hna_buff != NULL))
75 hna_global_add_orig(bat_priv, orig_node,
76 hna_buff, hna_buff_len);
77 }
78}
79
80static void update_route(struct bat_priv *bat_priv,
81 struct orig_node *orig_node,
82 struct neigh_node *neigh_node,
83 unsigned char *hna_buff, int hna_buff_len)
84{
85 /* route deleted */
86 if ((orig_node->router != NULL) && (neigh_node == NULL)) {
87
88 bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
89 orig_node->orig);
90 hna_global_del_orig(bat_priv, orig_node,
91 "originator timed out");
92
93 /* route added */
94 } else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
95
96 bat_dbg(DBG_ROUTES, bat_priv,
97 "Adding route towards: %pM (via %pM)\n",
98 orig_node->orig, neigh_node->addr);
99 hna_global_add_orig(bat_priv, orig_node,
100 hna_buff, hna_buff_len);
101
102 /* route changed */
103 } else {
104 bat_dbg(DBG_ROUTES, bat_priv,
105 "Changing route towards: %pM "
106 "(now via %pM - was via %pM)\n",
107 orig_node->orig, neigh_node->addr,
108 orig_node->router->addr);
109 }
110
111 orig_node->router = neigh_node;
112}
113
114
115void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
116 struct neigh_node *neigh_node, unsigned char *hna_buff,
117 int hna_buff_len)
118{
119
120 if (orig_node == NULL)
121 return;
122
123 if (orig_node->router != neigh_node)
124 update_route(bat_priv, orig_node, neigh_node,
125 hna_buff, hna_buff_len);
126 /* may be just HNA changed */
127 else
128 update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len);
129}
130
131static int is_bidirectional_neigh(struct orig_node *orig_node,
132 struct orig_node *orig_neigh_node,
133 struct batman_packet *batman_packet,
134 struct batman_if *if_incoming)
135{
136 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
137 struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
138 unsigned char total_count;
139
140 if (orig_node == orig_neigh_node) {
141 list_for_each_entry(tmp_neigh_node,
142 &orig_node->neigh_list,
143 list) {
144
145 if (compare_orig(tmp_neigh_node->addr,
146 orig_neigh_node->orig) &&
147 (tmp_neigh_node->if_incoming == if_incoming))
148 neigh_node = tmp_neigh_node;
149 }
150
151 if (!neigh_node)
152 neigh_node = create_neighbor(orig_node,
153 orig_neigh_node,
154 orig_neigh_node->orig,
155 if_incoming);
156 /* create_neighbor failed, return 0 */
157 if (!neigh_node)
158 return 0;
159
160 neigh_node->last_valid = jiffies;
161 } else {
162 /* find packet count of corresponding one hop neighbor */
163 list_for_each_entry(tmp_neigh_node,
164 &orig_neigh_node->neigh_list, list) {
165
166 if (compare_orig(tmp_neigh_node->addr,
167 orig_neigh_node->orig) &&
168 (tmp_neigh_node->if_incoming == if_incoming))
169 neigh_node = tmp_neigh_node;
170 }
171
172 if (!neigh_node)
173 neigh_node = create_neighbor(orig_neigh_node,
174 orig_neigh_node,
175 orig_neigh_node->orig,
176 if_incoming);
177 /* create_neighbor failed, return 0 */
178 if (!neigh_node)
179 return 0;
180 }
181
182 orig_node->last_valid = jiffies;
183
184 /* pay attention to not get a value bigger than 100 % */
185 total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] >
186 neigh_node->real_packet_count ?
187 neigh_node->real_packet_count :
188 orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
189
190 /* if we have too few packets (too less data) we set tq_own to zero */
191 /* if we receive too few packets it is not considered bidirectional */
192 if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
193 (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
194 orig_neigh_node->tq_own = 0;
195 else
196 /* neigh_node->real_packet_count is never zero as we
197 * only purge old information when getting new
198 * information */
199 orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) /
200 neigh_node->real_packet_count;
201
202 /*
203 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
204 * affect the nearly-symmetric links only a little, but
205 * punishes asymmetric links more. This will give a value
206 * between 0 and TQ_MAX_VALUE
207 */
208 orig_neigh_node->tq_asym_penalty =
209 TQ_MAX_VALUE -
210 (TQ_MAX_VALUE *
211 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
212 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
213 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
214 (TQ_LOCAL_WINDOW_SIZE *
215 TQ_LOCAL_WINDOW_SIZE *
216 TQ_LOCAL_WINDOW_SIZE);
217
218 batman_packet->tq = ((batman_packet->tq *
219 orig_neigh_node->tq_own *
220 orig_neigh_node->tq_asym_penalty) /
221 (TQ_MAX_VALUE * TQ_MAX_VALUE));
222
223 bat_dbg(DBG_BATMAN, bat_priv,
224 "bidirectional: "
225 "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
226 "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
227 "total tq: %3i\n",
228 orig_node->orig, orig_neigh_node->orig, total_count,
229 neigh_node->real_packet_count, orig_neigh_node->tq_own,
230 orig_neigh_node->tq_asym_penalty, batman_packet->tq);
231
232 /* if link has the minimum required transmission quality
233 * consider it bidirectional */
234 if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
235 return 1;
236
237 return 0;
238}
239
240static void update_orig(struct bat_priv *bat_priv,
241 struct orig_node *orig_node,
242 struct ethhdr *ethhdr,
243 struct batman_packet *batman_packet,
244 struct batman_if *if_incoming,
245 unsigned char *hna_buff, int hna_buff_len,
246 char is_duplicate)
247{
248 struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
249 int tmp_hna_buff_len;
250
251 bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
252 "Searching and updating originator entry of received packet\n");
253
254 list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
255 if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
256 (tmp_neigh_node->if_incoming == if_incoming)) {
257 neigh_node = tmp_neigh_node;
258 continue;
259 }
260
261 if (is_duplicate)
262 continue;
263
264 ring_buffer_set(tmp_neigh_node->tq_recv,
265 &tmp_neigh_node->tq_index, 0);
266 tmp_neigh_node->tq_avg =
267 ring_buffer_avg(tmp_neigh_node->tq_recv);
268 }
269
270 if (!neigh_node) {
271 struct orig_node *orig_tmp;
272
273 orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
274 if (!orig_tmp)
275 return;
276
277 neigh_node = create_neighbor(orig_node, orig_tmp,
278 ethhdr->h_source, if_incoming);
279 if (!neigh_node)
280 return;
281 } else
282 bat_dbg(DBG_BATMAN, bat_priv,
283 "Updating existing last-hop neighbor of originator\n");
284
285 orig_node->flags = batman_packet->flags;
286 neigh_node->last_valid = jiffies;
287
288 ring_buffer_set(neigh_node->tq_recv,
289 &neigh_node->tq_index,
290 batman_packet->tq);
291 neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
292
293 if (!is_duplicate) {
294 orig_node->last_ttl = batman_packet->ttl;
295 neigh_node->last_ttl = batman_packet->ttl;
296 }
297
298 tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ?
299 batman_packet->num_hna * ETH_ALEN : hna_buff_len);
300
301 /* if this neighbor already is our next hop there is nothing
302 * to change */
303 if (orig_node->router == neigh_node)
304 goto update_hna;
305
306 /* if this neighbor does not offer a better TQ we won't consider it */
307 if ((orig_node->router) &&
308 (orig_node->router->tq_avg > neigh_node->tq_avg))
309 goto update_hna;
310
311 /* if the TQ is the same and the link not more symetric we
312 * won't consider it either */
313 if ((orig_node->router) &&
314 ((neigh_node->tq_avg == orig_node->router->tq_avg) &&
315 (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num]
316 >= neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
317 goto update_hna;
318
319 update_routes(bat_priv, orig_node, neigh_node,
320 hna_buff, tmp_hna_buff_len);
321 goto update_gw;
322
323update_hna:
324 update_routes(bat_priv, orig_node, orig_node->router,
325 hna_buff, tmp_hna_buff_len);
326
327update_gw:
328 if (orig_node->gw_flags != batman_packet->gw_flags)
329 gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
330
331 orig_node->gw_flags = batman_packet->gw_flags;
332
333 /* restart gateway selection if fast or late switching was enabled */
334 if ((orig_node->gw_flags) &&
335 (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
336 (atomic_read(&bat_priv->gw_sel_class) > 2))
337 gw_check_election(bat_priv, orig_node);
338}
339
340/* checks whether the host restarted and is in the protection time.
341 * returns:
342 * 0 if the packet is to be accepted
343 * 1 if the packet is to be ignored.
344 */
345static int window_protected(struct bat_priv *bat_priv,
346 int32_t seq_num_diff,
347 unsigned long *last_reset)
348{
349 if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
350 || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
351 if (time_after(jiffies, *last_reset +
352 msecs_to_jiffies(RESET_PROTECTION_MS))) {
353
354 *last_reset = jiffies;
355 bat_dbg(DBG_BATMAN, bat_priv,
356 "old packet received, start protection\n");
357
358 return 0;
359 } else
360 return 1;
361 }
362 return 0;
363}
364
365/* processes a batman packet for all interfaces, adjusts the sequence number and
366 * finds out whether it is a duplicate.
367 * returns:
368 * 1 the packet is a duplicate
369 * 0 the packet has not yet been received
370 * -1 the packet is old and has been received while the seqno window
371 * was protected. Caller should drop it.
372 */
373static char count_real_packets(struct ethhdr *ethhdr,
374 struct batman_packet *batman_packet,
375 struct batman_if *if_incoming)
376{
377 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
378 struct orig_node *orig_node;
379 struct neigh_node *tmp_neigh_node;
380 char is_duplicate = 0;
381 int32_t seq_diff;
382 int need_update = 0;
383 int set_mark;
384
385 orig_node = get_orig_node(bat_priv, batman_packet->orig);
386 if (orig_node == NULL)
387 return 0;
388
389 seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
390
391 /* signalize caller that the packet is to be dropped. */
392 if (window_protected(bat_priv, seq_diff,
393 &orig_node->batman_seqno_reset))
394 return -1;
395
396 list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
397
398 is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
399 orig_node->last_real_seqno,
400 batman_packet->seqno);
401
402 if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
403 (tmp_neigh_node->if_incoming == if_incoming))
404 set_mark = 1;
405 else
406 set_mark = 0;
407
408 /* if the window moved, set the update flag. */
409 need_update |= bit_get_packet(bat_priv,
410 tmp_neigh_node->real_bits,
411 seq_diff, set_mark);
412
413 tmp_neigh_node->real_packet_count =
414 bit_packet_count(tmp_neigh_node->real_bits);
415 }
416
417 if (need_update) {
418 bat_dbg(DBG_BATMAN, bat_priv,
419 "updating last_seqno: old %d, new %d\n",
420 orig_node->last_real_seqno, batman_packet->seqno);
421 orig_node->last_real_seqno = batman_packet->seqno;
422 }
423
424 return is_duplicate;
425}
426
427/* copy primary address for bonding */
428static void mark_bonding_address(struct bat_priv *bat_priv,
429 struct orig_node *orig_node,
430 struct orig_node *orig_neigh_node,
431 struct batman_packet *batman_packet)
432
433{
434 if (batman_packet->flags & PRIMARIES_FIRST_HOP)
435 memcpy(orig_neigh_node->primary_addr,
436 orig_node->orig, ETH_ALEN);
437
438 return;
439}
440
441/* mark possible bond.candidates in the neighbor list */
442void update_bonding_candidates(struct bat_priv *bat_priv,
443 struct orig_node *orig_node)
444{
445 int candidates;
446 int interference_candidate;
447 int best_tq;
448 struct neigh_node *tmp_neigh_node, *tmp_neigh_node2;
449 struct neigh_node *first_candidate, *last_candidate;
450
451 /* update the candidates for this originator */
452 if (!orig_node->router) {
453 orig_node->bond.candidates = 0;
454 return;
455 }
456
457 best_tq = orig_node->router->tq_avg;
458
459 /* update bond.candidates */
460
461 candidates = 0;
462
463 /* mark other nodes which also received "PRIMARIES FIRST HOP" packets
464 * as "bonding partner" */
465
466 /* first, zero the list */
467 list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
468 tmp_neigh_node->next_bond_candidate = NULL;
469 }
470
471 first_candidate = NULL;
472 last_candidate = NULL;
473 list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
474
475 /* only consider if it has the same primary address ... */
476 if (memcmp(orig_node->orig,
477 tmp_neigh_node->orig_node->primary_addr,
478 ETH_ALEN) != 0)
479 continue;
480
481 /* ... and is good enough to be considered */
482 if (tmp_neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
483 continue;
484
485 /* check if we have another candidate with the same
486 * mac address or interface. If we do, we won't
487 * select this candidate because of possible interference. */
488
489 interference_candidate = 0;
490 list_for_each_entry(tmp_neigh_node2,
491 &orig_node->neigh_list, list) {
492
493 if (tmp_neigh_node2 == tmp_neigh_node)
494 continue;
495
496 /* we only care if the other candidate is even
497 * considered as candidate. */
498 if (tmp_neigh_node2->next_bond_candidate == NULL)
499 continue;
500
501
502 if ((tmp_neigh_node->if_incoming ==
503 tmp_neigh_node2->if_incoming)
504 || (memcmp(tmp_neigh_node->addr,
505 tmp_neigh_node2->addr, ETH_ALEN) == 0)) {
506
507 interference_candidate = 1;
508 break;
509 }
510 }
511 /* don't care further if it is an interference candidate */
512 if (interference_candidate)
513 continue;
514
515 if (first_candidate == NULL) {
516 first_candidate = tmp_neigh_node;
517 tmp_neigh_node->next_bond_candidate = first_candidate;
518 } else
519 tmp_neigh_node->next_bond_candidate = last_candidate;
520
521 last_candidate = tmp_neigh_node;
522
523 candidates++;
524 }
525
526 if (candidates > 0) {
527 first_candidate->next_bond_candidate = last_candidate;
528 orig_node->bond.selected = first_candidate;
529 }
530
531 orig_node->bond.candidates = candidates;
532}
533
534void receive_bat_packet(struct ethhdr *ethhdr,
535 struct batman_packet *batman_packet,
536 unsigned char *hna_buff, int hna_buff_len,
537 struct batman_if *if_incoming)
538{
539 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
540 struct batman_if *batman_if;
541 struct orig_node *orig_neigh_node, *orig_node;
542 char has_directlink_flag;
543 char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
544 char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
545 char is_duplicate;
546 uint32_t if_incoming_seqno;
547
548 /* Silently drop when the batman packet is actually not a
549 * correct packet.
550 *
551 * This might happen if a packet is padded (e.g. Ethernet has a
552 * minimum frame length of 64 byte) and the aggregation interprets
553 * it as an additional length.
554 *
555 * TODO: A more sane solution would be to have a bit in the
556 * batman_packet to detect whether the packet is the last
557 * packet in an aggregation. Here we expect that the padding
558 * is always zero (or not 0x01)
559 */
560 if (batman_packet->packet_type != BAT_PACKET)
561 return;
562
563 /* could be changed by schedule_own_packet() */
564 if_incoming_seqno = atomic_read(&if_incoming->seqno);
565
566 has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
567
568 is_single_hop_neigh = (compare_orig(ethhdr->h_source,
569 batman_packet->orig) ? 1 : 0);
570
571 bat_dbg(DBG_BATMAN, bat_priv,
572 "Received BATMAN packet via NB: %pM, IF: %s [%pM] "
573 "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
574 "TTL %d, V %d, IDF %d)\n",
575 ethhdr->h_source, if_incoming->net_dev->name,
576 if_incoming->net_dev->dev_addr, batman_packet->orig,
577 batman_packet->prev_sender, batman_packet->seqno,
578 batman_packet->tq, batman_packet->ttl, batman_packet->version,
579 has_directlink_flag);
580
581 rcu_read_lock();
582 list_for_each_entry_rcu(batman_if, &if_list, list) {
583 if (batman_if->if_status != IF_ACTIVE)
584 continue;
585
586 if (batman_if->soft_iface != if_incoming->soft_iface)
587 continue;
588
589 if (compare_orig(ethhdr->h_source,
590 batman_if->net_dev->dev_addr))
591 is_my_addr = 1;
592
593 if (compare_orig(batman_packet->orig,
594 batman_if->net_dev->dev_addr))
595 is_my_orig = 1;
596
597 if (compare_orig(batman_packet->prev_sender,
598 batman_if->net_dev->dev_addr))
599 is_my_oldorig = 1;
600
601 if (compare_orig(ethhdr->h_source, broadcast_addr))
602 is_broadcast = 1;
603 }
604 rcu_read_unlock();
605
606 if (batman_packet->version != COMPAT_VERSION) {
607 bat_dbg(DBG_BATMAN, bat_priv,
608 "Drop packet: incompatible batman version (%i)\n",
609 batman_packet->version);
610 return;
611 }
612
613 if (is_my_addr) {
614 bat_dbg(DBG_BATMAN, bat_priv,
615 "Drop packet: received my own broadcast (sender: %pM"
616 ")\n",
617 ethhdr->h_source);
618 return;
619 }
620
621 if (is_broadcast) {
622 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
623 "ignoring all packets with broadcast source addr (sender: %pM"
624 ")\n", ethhdr->h_source);
625 return;
626 }
627
628 if (is_my_orig) {
629 TYPE_OF_WORD *word;
630 int offset;
631
632 orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
633
634 if (!orig_neigh_node)
635 return;
636
637 /* neighbor has to indicate direct link and it has to
638 * come via the corresponding interface */
639 /* if received seqno equals last send seqno save new
640 * seqno for bidirectional check */
641 if (has_directlink_flag &&
642 compare_orig(if_incoming->net_dev->dev_addr,
643 batman_packet->orig) &&
644 (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
645 offset = if_incoming->if_num * NUM_WORDS;
646 word = &(orig_neigh_node->bcast_own[offset]);
647 bit_mark(word, 0);
648 orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
649 bit_packet_count(word);
650 }
651
652 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
653 "originator packet from myself (via neighbor)\n");
654 return;
655 }
656
657 if (is_my_oldorig) {
658 bat_dbg(DBG_BATMAN, bat_priv,
659 "Drop packet: ignoring all rebroadcast echos (sender: "
660 "%pM)\n", ethhdr->h_source);
661 return;
662 }
663
664 orig_node = get_orig_node(bat_priv, batman_packet->orig);
665 if (orig_node == NULL)
666 return;
667
668 is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
669
670 if (is_duplicate == -1) {
671 bat_dbg(DBG_BATMAN, bat_priv,
672 "Drop packet: packet within seqno protection time "
673 "(sender: %pM)\n", ethhdr->h_source);
674 return;
675 }
676
677 if (batman_packet->tq == 0) {
678 bat_dbg(DBG_BATMAN, bat_priv,
679 "Drop packet: originator packet with tq equal 0\n");
680 return;
681 }
682
683 /* avoid temporary routing loops */
684 if ((orig_node->router) &&
685 (orig_node->router->orig_node->router) &&
686 (compare_orig(orig_node->router->addr,
687 batman_packet->prev_sender)) &&
688 !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
689 (compare_orig(orig_node->router->addr,
690 orig_node->router->orig_node->router->addr))) {
691 bat_dbg(DBG_BATMAN, bat_priv,
692 "Drop packet: ignoring all rebroadcast packets that "
693 "may make me loop (sender: %pM)\n", ethhdr->h_source);
694 return;
695 }
696
697 /* if sender is a direct neighbor the sender mac equals
698 * originator mac */
699 orig_neigh_node = (is_single_hop_neigh ?
700 orig_node :
701 get_orig_node(bat_priv, ethhdr->h_source));
702 if (orig_neigh_node == NULL)
703 return;
704
705 /* drop packet if sender is not a direct neighbor and if we
706 * don't route towards it */
707 if (!is_single_hop_neigh &&
708 (orig_neigh_node->router == NULL)) {
709 bat_dbg(DBG_BATMAN, bat_priv,
710 "Drop packet: OGM via unknown neighbor!\n");
711 return;
712 }
713
714 is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
715 batman_packet, if_incoming);
716
717 /* update ranking if it is not a duplicate or has the same
718 * seqno and similar ttl as the non-duplicate */
719 if (is_bidirectional &&
720 (!is_duplicate ||
721 ((orig_node->last_real_seqno == batman_packet->seqno) &&
722 (orig_node->last_ttl - 3 <= batman_packet->ttl))))
723 update_orig(bat_priv, orig_node, ethhdr, batman_packet,
724 if_incoming, hna_buff, hna_buff_len, is_duplicate);
725
726 mark_bonding_address(bat_priv, orig_node,
727 orig_neigh_node, batman_packet);
728 update_bonding_candidates(bat_priv, orig_node);
729
730 /* is single hop (direct) neighbor */
731 if (is_single_hop_neigh) {
732
733 /* mark direct link on incoming interface */
734 schedule_forward_packet(orig_node, ethhdr, batman_packet,
735 1, hna_buff_len, if_incoming);
736
737 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
738 "rebroadcast neighbor packet with direct link flag\n");
739 return;
740 }
741
742 /* multihop originator */
743 if (!is_bidirectional) {
744 bat_dbg(DBG_BATMAN, bat_priv,
745 "Drop packet: not received via bidirectional link\n");
746 return;
747 }
748
749 if (is_duplicate) {
750 bat_dbg(DBG_BATMAN, bat_priv,
751 "Drop packet: duplicate packet received\n");
752 return;
753 }
754
755 bat_dbg(DBG_BATMAN, bat_priv,
756 "Forwarding packet: rebroadcast originator packet\n");
757 schedule_forward_packet(orig_node, ethhdr, batman_packet,
758 0, hna_buff_len, if_incoming);
759}
760
761int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
762{
763 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
764 struct ethhdr *ethhdr;
765
766 /* drop packet if it has not necessary minimum size */
767 if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet))))
768 return NET_RX_DROP;
769
770 ethhdr = (struct ethhdr *)skb_mac_header(skb);
771
772 /* packet with broadcast indication but unicast recipient */
773 if (!is_broadcast_ether_addr(ethhdr->h_dest))
774 return NET_RX_DROP;
775
776 /* packet with broadcast sender address */
777 if (is_broadcast_ether_addr(ethhdr->h_source))
778 return NET_RX_DROP;
779
780 /* create a copy of the skb, if needed, to modify it. */
781 if (skb_cow(skb, 0) < 0)
782 return NET_RX_DROP;
783
784 /* keep skb linear */
785 if (skb_linearize(skb) < 0)
786 return NET_RX_DROP;
787
788 ethhdr = (struct ethhdr *)skb_mac_header(skb);
789
790 spin_lock_bh(&bat_priv->orig_hash_lock);
791 receive_aggr_bat_packet(ethhdr,
792 skb->data,
793 skb_headlen(skb),
794 batman_if);
795 spin_unlock_bh(&bat_priv->orig_hash_lock);
796
797 kfree_skb(skb);
798 return NET_RX_SUCCESS;
799}
800
801static int recv_my_icmp_packet(struct bat_priv *bat_priv,
802 struct sk_buff *skb, size_t icmp_len)
803{
804 struct orig_node *orig_node;
805 struct icmp_packet_rr *icmp_packet;
806 struct ethhdr *ethhdr;
807 struct batman_if *batman_if;
808 int ret;
809 uint8_t dstaddr[ETH_ALEN];
810
811 icmp_packet = (struct icmp_packet_rr *)skb->data;
812 ethhdr = (struct ethhdr *)skb_mac_header(skb);
813
814 /* add data to device queue */
815 if (icmp_packet->msg_type != ECHO_REQUEST) {
816 bat_socket_receive_packet(icmp_packet, icmp_len);
817 return NET_RX_DROP;
818 }
819
820 if (!bat_priv->primary_if)
821 return NET_RX_DROP;
822
823 /* answer echo request (ping) */
824 /* get routing information */
825 spin_lock_bh(&bat_priv->orig_hash_lock);
826 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
827 compare_orig, choose_orig,
828 icmp_packet->orig));
829 ret = NET_RX_DROP;
830
831 if ((orig_node != NULL) &&
832 (orig_node->router != NULL)) {
833
834 /* don't lock while sending the packets ... we therefore
835 * copy the required data before sending */
836 batman_if = orig_node->router->if_incoming;
837 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
838 spin_unlock_bh(&bat_priv->orig_hash_lock);
839
840 /* create a copy of the skb, if needed, to modify it. */
841 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
842 return NET_RX_DROP;
843
844 icmp_packet = (struct icmp_packet_rr *)skb->data;
845 ethhdr = (struct ethhdr *)skb_mac_header(skb);
846
847 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
848 memcpy(icmp_packet->orig,
849 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
850 icmp_packet->msg_type = ECHO_REPLY;
851 icmp_packet->ttl = TTL;
852
853 send_skb_packet(skb, batman_if, dstaddr);
854 ret = NET_RX_SUCCESS;
855
856 } else
857 spin_unlock_bh(&bat_priv->orig_hash_lock);
858
859 return ret;
860}
861
862static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
863 struct sk_buff *skb, size_t icmp_len)
864{
865 struct orig_node *orig_node;
866 struct icmp_packet *icmp_packet;
867 struct ethhdr *ethhdr;
868 struct batman_if *batman_if;
869 int ret;
870 uint8_t dstaddr[ETH_ALEN];
871
872 icmp_packet = (struct icmp_packet *)skb->data;
873 ethhdr = (struct ethhdr *)skb_mac_header(skb);
874
875 /* send TTL exceeded if packet is an echo request (traceroute) */
876 if (icmp_packet->msg_type != ECHO_REQUEST) {
877 pr_debug("Warning - can't forward icmp packet from %pM to "
878 "%pM: ttl exceeded\n", icmp_packet->orig,
879 icmp_packet->dst);
880 return NET_RX_DROP;
881 }
882
883 if (!bat_priv->primary_if)
884 return NET_RX_DROP;
885
886 /* get routing information */
887 spin_lock_bh(&bat_priv->orig_hash_lock);
888 orig_node = ((struct orig_node *)
889 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
890 icmp_packet->orig));
891 ret = NET_RX_DROP;
892
893 if ((orig_node != NULL) &&
894 (orig_node->router != NULL)) {
895
896 /* don't lock while sending the packets ... we therefore
897 * copy the required data before sending */
898 batman_if = orig_node->router->if_incoming;
899 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
900 spin_unlock_bh(&bat_priv->orig_hash_lock);
901
902 /* create a copy of the skb, if needed, to modify it. */
903 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
904 return NET_RX_DROP;
905
906 icmp_packet = (struct icmp_packet *) skb->data;
907 ethhdr = (struct ethhdr *)skb_mac_header(skb);
908
909 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
910 memcpy(icmp_packet->orig,
911 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
912 icmp_packet->msg_type = TTL_EXCEEDED;
913 icmp_packet->ttl = TTL;
914
915 send_skb_packet(skb, batman_if, dstaddr);
916 ret = NET_RX_SUCCESS;
917
918 } else
919 spin_unlock_bh(&bat_priv->orig_hash_lock);
920
921 return ret;
922}
923
924
925int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
926{
927 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
928 struct icmp_packet_rr *icmp_packet;
929 struct ethhdr *ethhdr;
930 struct orig_node *orig_node;
931 struct batman_if *batman_if;
932 int hdr_size = sizeof(struct icmp_packet);
933 int ret;
934 uint8_t dstaddr[ETH_ALEN];
935
936 /**
937 * we truncate all incoming icmp packets if they don't match our size
938 */
939 if (skb->len >= sizeof(struct icmp_packet_rr))
940 hdr_size = sizeof(struct icmp_packet_rr);
941
942 /* drop packet if it has not necessary minimum size */
943 if (unlikely(!pskb_may_pull(skb, hdr_size)))
944 return NET_RX_DROP;
945
946 ethhdr = (struct ethhdr *)skb_mac_header(skb);
947
948 /* packet with unicast indication but broadcast recipient */
949 if (is_broadcast_ether_addr(ethhdr->h_dest))
950 return NET_RX_DROP;
951
952 /* packet with broadcast sender address */
953 if (is_broadcast_ether_addr(ethhdr->h_source))
954 return NET_RX_DROP;
955
956 /* not for me */
957 if (!is_my_mac(ethhdr->h_dest))
958 return NET_RX_DROP;
959
960 icmp_packet = (struct icmp_packet_rr *)skb->data;
961
962 /* add record route information if not full */
963 if ((hdr_size == sizeof(struct icmp_packet_rr)) &&
964 (icmp_packet->rr_cur < BAT_RR_LEN)) {
965 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
966 ethhdr->h_dest, ETH_ALEN);
967 icmp_packet->rr_cur++;
968 }
969
970 /* packet for me */
971 if (is_my_mac(icmp_packet->dst))
972 return recv_my_icmp_packet(bat_priv, skb, hdr_size);
973
974 /* TTL exceeded */
975 if (icmp_packet->ttl < 2)
976 return recv_icmp_ttl_exceeded(bat_priv, skb, hdr_size);
977
978 ret = NET_RX_DROP;
979
980 /* get routing information */
981 spin_lock_bh(&bat_priv->orig_hash_lock);
982 orig_node = ((struct orig_node *)
983 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
984 icmp_packet->dst));
985
986 if ((orig_node != NULL) &&
987 (orig_node->router != NULL)) {
988
989 /* don't lock while sending the packets ... we therefore
990 * copy the required data before sending */
991 batman_if = orig_node->router->if_incoming;
992 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
993 spin_unlock_bh(&bat_priv->orig_hash_lock);
994
995 /* create a copy of the skb, if needed, to modify it. */
996 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
997 return NET_RX_DROP;
998
999 icmp_packet = (struct icmp_packet_rr *)skb->data;
1000 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1001
1002 /* decrement ttl */
1003 icmp_packet->ttl--;
1004
1005 /* route it */
1006 send_skb_packet(skb, batman_if, dstaddr);
1007 ret = NET_RX_SUCCESS;
1008
1009 } else
1010 spin_unlock_bh(&bat_priv->orig_hash_lock);
1011
1012 return ret;
1013}
1014
1015/* find a suitable router for this originator, and use
1016 * bonding if possible. */
1017struct neigh_node *find_router(struct bat_priv *bat_priv,
1018 struct orig_node *orig_node,
1019 struct batman_if *recv_if)
1020{
1021 struct orig_node *primary_orig_node;
1022 struct orig_node *router_orig;
1023 struct neigh_node *router, *first_candidate, *best_router;
1024 static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
1025 int bonding_enabled;
1026
1027 if (!orig_node)
1028 return NULL;
1029
1030 if (!orig_node->router)
1031 return NULL;
1032
1033 /* without bonding, the first node should
1034 * always choose the default router. */
1035
1036 bonding_enabled = atomic_read(&bat_priv->bonding);
1037
1038 if ((!recv_if) && (!bonding_enabled))
1039 return orig_node->router;
1040
1041 router_orig = orig_node->router->orig_node;
1042
1043 /* if we have something in the primary_addr, we can search
1044 * for a potential bonding candidate. */
1045 if (memcmp(router_orig->primary_addr, zero_mac, ETH_ALEN) == 0)
1046 return orig_node->router;
1047
1048 /* find the orig_node which has the primary interface. might
1049 * even be the same as our router_orig in many cases */
1050
1051 if (memcmp(router_orig->primary_addr,
1052 router_orig->orig, ETH_ALEN) == 0) {
1053 primary_orig_node = router_orig;
1054 } else {
1055 primary_orig_node = hash_find(bat_priv->orig_hash, compare_orig,
1056 choose_orig,
1057 router_orig->primary_addr);
1058
1059 if (!primary_orig_node)
1060 return orig_node->router;
1061 }
1062
1063 /* with less than 2 candidates, we can't do any
1064 * bonding and prefer the original router. */
1065
1066 if (primary_orig_node->bond.candidates < 2)
1067 return orig_node->router;
1068
1069
1070 /* all nodes between should choose a candidate which
1071 * is is not on the interface where the packet came
1072 * in. */
1073 first_candidate = primary_orig_node->bond.selected;
1074 router = first_candidate;
1075
1076 if (bonding_enabled) {
1077 /* in the bonding case, send the packets in a round
1078 * robin fashion over the remaining interfaces. */
1079 do {
1080 /* recv_if == NULL on the first node. */
1081 if (router->if_incoming != recv_if)
1082 break;
1083
1084 router = router->next_bond_candidate;
1085 } while (router != first_candidate);
1086
1087 primary_orig_node->bond.selected = router->next_bond_candidate;
1088
1089 } else {
1090 /* if bonding is disabled, use the best of the
1091 * remaining candidates which are not using
1092 * this interface. */
1093 best_router = first_candidate;
1094
1095 do {
1096 /* recv_if == NULL on the first node. */
1097 if ((router->if_incoming != recv_if) &&
1098 (router->tq_avg > best_router->tq_avg))
1099 best_router = router;
1100
1101 router = router->next_bond_candidate;
1102 } while (router != first_candidate);
1103
1104 router = best_router;
1105 }
1106
1107 return router;
1108}
1109
1110static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
1111{
1112 struct ethhdr *ethhdr;
1113
1114 /* drop packet if it has not necessary minimum size */
1115 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1116 return -1;
1117
1118 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1119
1120 /* packet with unicast indication but broadcast recipient */
1121 if (is_broadcast_ether_addr(ethhdr->h_dest))
1122 return -1;
1123
1124 /* packet with broadcast sender address */
1125 if (is_broadcast_ether_addr(ethhdr->h_source))
1126 return -1;
1127
1128 /* not for me */
1129 if (!is_my_mac(ethhdr->h_dest))
1130 return -1;
1131
1132 return 0;
1133}
1134
1135int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1136 int hdr_size)
1137{
1138 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1139 struct orig_node *orig_node;
1140 struct neigh_node *router;
1141 struct batman_if *batman_if;
1142 uint8_t dstaddr[ETH_ALEN];
1143 struct unicast_packet *unicast_packet;
1144 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
1145 int ret;
1146 struct sk_buff *new_skb;
1147
1148 unicast_packet = (struct unicast_packet *)skb->data;
1149
1150 /* TTL exceeded */
1151 if (unicast_packet->ttl < 2) {
1152 pr_debug("Warning - can't forward unicast packet from %pM to "
1153 "%pM: ttl exceeded\n", ethhdr->h_source,
1154 unicast_packet->dest);
1155 return NET_RX_DROP;
1156 }
1157
1158 /* get routing information */
1159 spin_lock_bh(&bat_priv->orig_hash_lock);
1160 orig_node = ((struct orig_node *)
1161 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
1162 unicast_packet->dest));
1163
1164 router = find_router(bat_priv, orig_node, recv_if);
1165
1166 if (!router) {
1167 spin_unlock_bh(&bat_priv->orig_hash_lock);
1168 return NET_RX_DROP;
1169 }
1170
1171 /* don't lock while sending the packets ... we therefore
1172 * copy the required data before sending */
1173
1174 batman_if = router->if_incoming;
1175 memcpy(dstaddr, router->addr, ETH_ALEN);
1176
1177 spin_unlock_bh(&bat_priv->orig_hash_lock);
1178
1179 /* create a copy of the skb, if needed, to modify it. */
1180 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1181 return NET_RX_DROP;
1182
1183 unicast_packet = (struct unicast_packet *)skb->data;
1184
1185 if (unicast_packet->packet_type == BAT_UNICAST &&
1186 atomic_read(&bat_priv->fragmentation) &&
1187 skb->len > batman_if->net_dev->mtu)
1188 return frag_send_skb(skb, bat_priv, batman_if,
1189 dstaddr);
1190
1191 if (unicast_packet->packet_type == BAT_UNICAST_FRAG &&
1192 2 * skb->len - hdr_size <= batman_if->net_dev->mtu) {
1193
1194 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1195
1196 if (ret == NET_RX_DROP)
1197 return NET_RX_DROP;
1198
1199 /* packet was buffered for late merge */
1200 if (!new_skb)
1201 return NET_RX_SUCCESS;
1202
1203 skb = new_skb;
1204 unicast_packet = (struct unicast_packet *)skb->data;
1205 }
1206
1207 /* decrement ttl */
1208 unicast_packet->ttl--;
1209
1210 /* route it */
1211 send_skb_packet(skb, batman_if, dstaddr);
1212
1213 return NET_RX_SUCCESS;
1214}
1215
1216int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
1217{
1218 struct unicast_packet *unicast_packet;
1219 int hdr_size = sizeof(struct unicast_packet);
1220
1221 if (check_unicast_packet(skb, hdr_size) < 0)
1222 return NET_RX_DROP;
1223
1224 unicast_packet = (struct unicast_packet *)skb->data;
1225
1226 /* packet for me */
1227 if (is_my_mac(unicast_packet->dest)) {
1228 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
1229 return NET_RX_SUCCESS;
1230 }
1231
1232 return route_unicast_packet(skb, recv_if, hdr_size);
1233}
1234
1235int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
1236{
1237 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1238 struct unicast_frag_packet *unicast_packet;
1239 int hdr_size = sizeof(struct unicast_frag_packet);
1240 struct sk_buff *new_skb = NULL;
1241 int ret;
1242
1243 if (check_unicast_packet(skb, hdr_size) < 0)
1244 return NET_RX_DROP;
1245
1246 unicast_packet = (struct unicast_frag_packet *)skb->data;
1247
1248 /* packet for me */
1249 if (is_my_mac(unicast_packet->dest)) {
1250
1251 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1252
1253 if (ret == NET_RX_DROP)
1254 return NET_RX_DROP;
1255
1256 /* packet was buffered for late merge */
1257 if (!new_skb)
1258 return NET_RX_SUCCESS;
1259
1260 interface_rx(recv_if->soft_iface, new_skb, recv_if,
1261 sizeof(struct unicast_packet));
1262 return NET_RX_SUCCESS;
1263 }
1264
1265 return route_unicast_packet(skb, recv_if, hdr_size);
1266}
1267
1268
1269int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
1270{
1271 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1272 struct orig_node *orig_node;
1273 struct bcast_packet *bcast_packet;
1274 struct ethhdr *ethhdr;
1275 int hdr_size = sizeof(struct bcast_packet);
1276 int32_t seq_diff;
1277
1278 /* drop packet if it has not necessary minimum size */
1279 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1280 return NET_RX_DROP;
1281
1282 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1283
1284 /* packet with broadcast indication but unicast recipient */
1285 if (!is_broadcast_ether_addr(ethhdr->h_dest))
1286 return NET_RX_DROP;
1287
1288 /* packet with broadcast sender address */
1289 if (is_broadcast_ether_addr(ethhdr->h_source))
1290 return NET_RX_DROP;
1291
1292 /* ignore broadcasts sent by myself */
1293 if (is_my_mac(ethhdr->h_source))
1294 return NET_RX_DROP;
1295
1296 bcast_packet = (struct bcast_packet *)skb->data;
1297
1298 /* ignore broadcasts originated by myself */
1299 if (is_my_mac(bcast_packet->orig))
1300 return NET_RX_DROP;
1301
1302 if (bcast_packet->ttl < 2)
1303 return NET_RX_DROP;
1304
1305 spin_lock_bh(&bat_priv->orig_hash_lock);
1306 orig_node = ((struct orig_node *)
1307 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
1308 bcast_packet->orig));
1309
1310 if (orig_node == NULL) {
1311 spin_unlock_bh(&bat_priv->orig_hash_lock);
1312 return NET_RX_DROP;
1313 }
1314
1315 /* check whether the packet is a duplicate */
1316 if (get_bit_status(orig_node->bcast_bits,
1317 orig_node->last_bcast_seqno,
1318 ntohl(bcast_packet->seqno))) {
1319 spin_unlock_bh(&bat_priv->orig_hash_lock);
1320 return NET_RX_DROP;
1321 }
1322
1323 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
1324
1325 /* check whether the packet is old and the host just restarted. */
1326 if (window_protected(bat_priv, seq_diff,
1327 &orig_node->bcast_seqno_reset)) {
1328 spin_unlock_bh(&bat_priv->orig_hash_lock);
1329 return NET_RX_DROP;
1330 }
1331
1332 /* mark broadcast in flood history, update window position
1333 * if required. */
1334 if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
1335 orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
1336
1337 spin_unlock_bh(&bat_priv->orig_hash_lock);
1338 /* rebroadcast packet */
1339 add_bcast_packet_to_list(bat_priv, skb);
1340
1341 /* broadcast for me */
1342 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
1343
1344 return NET_RX_SUCCESS;
1345}
1346
1347int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if)
1348{
1349 struct vis_packet *vis_packet;
1350 struct ethhdr *ethhdr;
1351 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1352 int hdr_size = sizeof(struct vis_packet);
1353
1354 /* keep skb linear */
1355 if (skb_linearize(skb) < 0)
1356 return NET_RX_DROP;
1357
1358 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1359 return NET_RX_DROP;
1360
1361 vis_packet = (struct vis_packet *)skb->data;
1362 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1363
1364 /* not for me */
1365 if (!is_my_mac(ethhdr->h_dest))
1366 return NET_RX_DROP;
1367
1368 /* ignore own packets */
1369 if (is_my_mac(vis_packet->vis_orig))
1370 return NET_RX_DROP;
1371
1372 if (is_my_mac(vis_packet->sender_orig))
1373 return NET_RX_DROP;
1374
1375 switch (vis_packet->vis_type) {
1376 case VIS_TYPE_SERVER_SYNC:
1377 receive_server_sync_packet(bat_priv, vis_packet,
1378 skb_headlen(skb));
1379 break;
1380
1381 case VIS_TYPE_CLIENT_UPDATE:
1382 receive_client_update_packet(bat_priv, vis_packet,
1383 skb_headlen(skb));
1384 break;
1385
1386 default: /* ignore unknown packet */
1387 break;
1388 }
1389
1390 /* We take a copy of the data in the packet, so we should
1391 always free the skbuf. */
1392 return NET_RX_DROP;
1393}
diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h
deleted file mode 100644
index f108f230bfdb..000000000000
--- a/drivers/staging/batman-adv/routing.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_ROUTING_H_
23#define _NET_BATMAN_ADV_ROUTING_H_
24
25#include "types.h"
26
27void slide_own_bcast_window(struct batman_if *batman_if);
28void receive_bat_packet(struct ethhdr *ethhdr,
29 struct batman_packet *batman_packet,
30 unsigned char *hna_buff, int hna_buff_len,
31 struct batman_if *if_incoming);
32void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
33 struct neigh_node *neigh_node, unsigned char *hna_buff,
34 int hna_buff_len);
35int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
36 int hdr_size);
37int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if);
38int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if);
39int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if);
40int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if);
41int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if);
42int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if);
43struct neigh_node *find_router(struct bat_priv *bat_priv,
44 struct orig_node *orig_node, struct batman_if *recv_if);
45void update_bonding_candidates(struct bat_priv *bat_priv,
46 struct orig_node *orig_node);
47
48#endif /* _NET_BATMAN_ADV_ROUTING_H_ */
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c
deleted file mode 100644
index 36945dc5a44b..000000000000
--- a/drivers/staging/batman-adv/send.c
+++ /dev/null
@@ -1,586 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "send.h"
24#include "routing.h"
25#include "translation-table.h"
26#include "soft-interface.h"
27#include "hard-interface.h"
28#include "types.h"
29#include "vis.h"
30#include "aggregation.h"
31#include "gateway_common.h"
32#include "originator.h"
33
34
35static void send_outstanding_bcast_packet(struct work_struct *work);
36
37/* apply hop penalty for a normal link */
38static uint8_t hop_penalty(const uint8_t tq, struct bat_priv *bat_priv)
39{
40 int hop_penalty = atomic_read(&bat_priv->hop_penalty);
41 return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE);
42}
43
44/* when do we schedule our own packet to be sent */
45static unsigned long own_send_time(struct bat_priv *bat_priv)
46{
47 return jiffies + msecs_to_jiffies(
48 atomic_read(&bat_priv->orig_interval) -
49 JITTER + (random32() % 2*JITTER));
50}
51
52/* when do we schedule a forwarded packet to be sent */
53static unsigned long forward_send_time(struct bat_priv *bat_priv)
54{
55 return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
56}
57
58/* send out an already prepared packet to the given address via the
59 * specified batman interface */
60int send_skb_packet(struct sk_buff *skb,
61 struct batman_if *batman_if,
62 uint8_t *dst_addr)
63{
64 struct ethhdr *ethhdr;
65
66 if (batman_if->if_status != IF_ACTIVE)
67 goto send_skb_err;
68
69 if (unlikely(!batman_if->net_dev))
70 goto send_skb_err;
71
72 if (!(batman_if->net_dev->flags & IFF_UP)) {
73 pr_warning("Interface %s is not up - can't send packet via "
74 "that interface!\n", batman_if->net_dev->name);
75 goto send_skb_err;
76 }
77
78 /* push to the ethernet header. */
79 if (my_skb_head_push(skb, sizeof(struct ethhdr)) < 0)
80 goto send_skb_err;
81
82 skb_reset_mac_header(skb);
83
84 ethhdr = (struct ethhdr *) skb_mac_header(skb);
85 memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN);
86 memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
87 ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
88
89 skb_set_network_header(skb, ETH_HLEN);
90 skb->priority = TC_PRIO_CONTROL;
91 skb->protocol = __constant_htons(ETH_P_BATMAN);
92
93 skb->dev = batman_if->net_dev;
94
95 /* dev_queue_xmit() returns a negative result on error. However on
96 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
97 * (which is > 0). This will not be treated as an error. */
98
99 return dev_queue_xmit(skb);
100send_skb_err:
101 kfree_skb(skb);
102 return NET_XMIT_DROP;
103}
104
105/* Send a packet to a given interface */
106static void send_packet_to_if(struct forw_packet *forw_packet,
107 struct batman_if *batman_if)
108{
109 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
110 char *fwd_str;
111 uint8_t packet_num;
112 int16_t buff_pos;
113 struct batman_packet *batman_packet;
114 struct sk_buff *skb;
115
116 if (batman_if->if_status != IF_ACTIVE)
117 return;
118
119 packet_num = 0;
120 buff_pos = 0;
121 batman_packet = (struct batman_packet *)forw_packet->skb->data;
122
123 /* adjust all flags and log packets */
124 while (aggregated_packet(buff_pos,
125 forw_packet->packet_len,
126 batman_packet->num_hna)) {
127
128 /* we might have aggregated direct link packets with an
129 * ordinary base packet */
130 if ((forw_packet->direct_link_flags & (1 << packet_num)) &&
131 (forw_packet->if_incoming == batman_if))
132 batman_packet->flags |= DIRECTLINK;
133 else
134 batman_packet->flags &= ~DIRECTLINK;
135
136 fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
137 "Sending own" :
138 "Forwarding"));
139 bat_dbg(DBG_BATMAN, bat_priv,
140 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
141 " IDF %s) on interface %s [%pM]\n",
142 fwd_str, (packet_num > 0 ? "aggregated " : ""),
143 batman_packet->orig, ntohl(batman_packet->seqno),
144 batman_packet->tq, batman_packet->ttl,
145 (batman_packet->flags & DIRECTLINK ?
146 "on" : "off"),
147 batman_if->net_dev->name, batman_if->net_dev->dev_addr);
148
149 buff_pos += sizeof(struct batman_packet) +
150 (batman_packet->num_hna * ETH_ALEN);
151 packet_num++;
152 batman_packet = (struct batman_packet *)
153 (forw_packet->skb->data + buff_pos);
154 }
155
156 /* create clone because function is called more than once */
157 skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
158 if (skb)
159 send_skb_packet(skb, batman_if, broadcast_addr);
160}
161
162/* send a batman packet */
163static void send_packet(struct forw_packet *forw_packet)
164{
165 struct batman_if *batman_if;
166 struct net_device *soft_iface;
167 struct bat_priv *bat_priv;
168 struct batman_packet *batman_packet =
169 (struct batman_packet *)(forw_packet->skb->data);
170 unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
171
172 if (!forw_packet->if_incoming) {
173 pr_err("Error - can't forward packet: incoming iface not "
174 "specified\n");
175 return;
176 }
177
178 soft_iface = forw_packet->if_incoming->soft_iface;
179 bat_priv = netdev_priv(soft_iface);
180
181 if (forw_packet->if_incoming->if_status != IF_ACTIVE)
182 return;
183
184 /* multihomed peer assumed */
185 /* non-primary OGMs are only broadcasted on their interface */
186 if ((directlink && (batman_packet->ttl == 1)) ||
187 (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
188
189 /* FIXME: what about aggregated packets ? */
190 bat_dbg(DBG_BATMAN, bat_priv,
191 "%s packet (originator %pM, seqno %d, TTL %d) "
192 "on interface %s [%pM]\n",
193 (forw_packet->own ? "Sending own" : "Forwarding"),
194 batman_packet->orig, ntohl(batman_packet->seqno),
195 batman_packet->ttl,
196 forw_packet->if_incoming->net_dev->name,
197 forw_packet->if_incoming->net_dev->dev_addr);
198
199 /* skb is only used once and than forw_packet is free'd */
200 send_skb_packet(forw_packet->skb, forw_packet->if_incoming,
201 broadcast_addr);
202 forw_packet->skb = NULL;
203
204 return;
205 }
206
207 /* broadcast on every interface */
208 rcu_read_lock();
209 list_for_each_entry_rcu(batman_if, &if_list, list) {
210 if (batman_if->soft_iface != soft_iface)
211 continue;
212
213 send_packet_to_if(forw_packet, batman_if);
214 }
215 rcu_read_unlock();
216}
217
218static void rebuild_batman_packet(struct bat_priv *bat_priv,
219 struct batman_if *batman_if)
220{
221 int new_len;
222 unsigned char *new_buff;
223 struct batman_packet *batman_packet;
224
225 new_len = sizeof(struct batman_packet) +
226 (bat_priv->num_local_hna * ETH_ALEN);
227 new_buff = kmalloc(new_len, GFP_ATOMIC);
228
229 /* keep old buffer if kmalloc should fail */
230 if (new_buff) {
231 memcpy(new_buff, batman_if->packet_buff,
232 sizeof(struct batman_packet));
233 batman_packet = (struct batman_packet *)new_buff;
234
235 batman_packet->num_hna = hna_local_fill_buffer(bat_priv,
236 new_buff + sizeof(struct batman_packet),
237 new_len - sizeof(struct batman_packet));
238
239 kfree(batman_if->packet_buff);
240 batman_if->packet_buff = new_buff;
241 batman_if->packet_len = new_len;
242 }
243}
244
245void schedule_own_packet(struct batman_if *batman_if)
246{
247 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
248 unsigned long send_time;
249 struct batman_packet *batman_packet;
250 int vis_server;
251
252 if ((batman_if->if_status == IF_NOT_IN_USE) ||
253 (batman_if->if_status == IF_TO_BE_REMOVED))
254 return;
255
256 vis_server = atomic_read(&bat_priv->vis_mode);
257
258 /**
259 * the interface gets activated here to avoid race conditions between
260 * the moment of activating the interface in
261 * hardif_activate_interface() where the originator mac is set and
262 * outdated packets (especially uninitialized mac addresses) in the
263 * packet queue
264 */
265 if (batman_if->if_status == IF_TO_BE_ACTIVATED)
266 batman_if->if_status = IF_ACTIVE;
267
268 /* if local hna has changed and interface is a primary interface */
269 if ((atomic_read(&bat_priv->hna_local_changed)) &&
270 (batman_if == bat_priv->primary_if))
271 rebuild_batman_packet(bat_priv, batman_if);
272
273 /**
274 * NOTE: packet_buff might just have been re-allocated in
275 * rebuild_batman_packet()
276 */
277 batman_packet = (struct batman_packet *)batman_if->packet_buff;
278
279 /* change sequence number to network order */
280 batman_packet->seqno =
281 htonl((uint32_t)atomic_read(&batman_if->seqno));
282
283 if (vis_server == VIS_TYPE_SERVER_SYNC)
284 batman_packet->flags |= VIS_SERVER;
285 else
286 batman_packet->flags &= ~VIS_SERVER;
287
288 if ((batman_if == bat_priv->primary_if) &&
289 (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
290 batman_packet->gw_flags =
291 (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
292 else
293 batman_packet->gw_flags = 0;
294
295 atomic_inc(&batman_if->seqno);
296
297 slide_own_bcast_window(batman_if);
298 send_time = own_send_time(bat_priv);
299 add_bat_packet_to_list(bat_priv,
300 batman_if->packet_buff,
301 batman_if->packet_len,
302 batman_if, 1, send_time);
303}
304
305void schedule_forward_packet(struct orig_node *orig_node,
306 struct ethhdr *ethhdr,
307 struct batman_packet *batman_packet,
308 uint8_t directlink, int hna_buff_len,
309 struct batman_if *if_incoming)
310{
311 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
312 unsigned char in_tq, in_ttl, tq_avg = 0;
313 unsigned long send_time;
314
315 if (batman_packet->ttl <= 1) {
316 bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
317 return;
318 }
319
320 in_tq = batman_packet->tq;
321 in_ttl = batman_packet->ttl;
322
323 batman_packet->ttl--;
324 memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
325
326 /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
327 * of our best tq value */
328 if ((orig_node->router) && (orig_node->router->tq_avg != 0)) {
329
330 /* rebroadcast ogm of best ranking neighbor as is */
331 if (!compare_orig(orig_node->router->addr, ethhdr->h_source)) {
332 batman_packet->tq = orig_node->router->tq_avg;
333
334 if (orig_node->router->last_ttl)
335 batman_packet->ttl = orig_node->router->last_ttl
336 - 1;
337 }
338
339 tq_avg = orig_node->router->tq_avg;
340 }
341
342 /* apply hop penalty */
343 batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv);
344
345 bat_dbg(DBG_BATMAN, bat_priv,
346 "Forwarding packet: tq_orig: %i, tq_avg: %i, "
347 "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
348 in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
349 batman_packet->ttl);
350
351 batman_packet->seqno = htonl(batman_packet->seqno);
352
353 /* switch of primaries first hop flag when forwarding */
354 batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
355 if (directlink)
356 batman_packet->flags |= DIRECTLINK;
357 else
358 batman_packet->flags &= ~DIRECTLINK;
359
360 send_time = forward_send_time(bat_priv);
361 add_bat_packet_to_list(bat_priv,
362 (unsigned char *)batman_packet,
363 sizeof(struct batman_packet) + hna_buff_len,
364 if_incoming, 0, send_time);
365}
366
367static void forw_packet_free(struct forw_packet *forw_packet)
368{
369 if (forw_packet->skb)
370 kfree_skb(forw_packet->skb);
371 kfree(forw_packet);
372}
373
374static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
375 struct forw_packet *forw_packet,
376 unsigned long send_time)
377{
378 INIT_HLIST_NODE(&forw_packet->list);
379
380 /* add new packet to packet list */
381 spin_lock_bh(&bat_priv->forw_bcast_list_lock);
382 hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list);
383 spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
384
385 /* start timer for this packet */
386 INIT_DELAYED_WORK(&forw_packet->delayed_work,
387 send_outstanding_bcast_packet);
388 queue_delayed_work(bat_event_workqueue, &forw_packet->delayed_work,
389 send_time);
390}
391
392#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
393/* add a broadcast packet to the queue and setup timers. broadcast packets
394 * are sent multiple times to increase probability for beeing received.
395 *
396 * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
397 * errors.
398 *
399 * The skb is not consumed, so the caller should make sure that the
400 * skb is freed. */
401int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
402{
403 struct forw_packet *forw_packet;
404 struct bcast_packet *bcast_packet;
405
406 if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
407 bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
408 goto out;
409 }
410
411 if (!bat_priv->primary_if)
412 goto out;
413
414 forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
415
416 if (!forw_packet)
417 goto out_and_inc;
418
419 skb = skb_copy(skb, GFP_ATOMIC);
420 if (!skb)
421 goto packet_free;
422
423 /* as we have a copy now, it is safe to decrease the TTL */
424 bcast_packet = (struct bcast_packet *)skb->data;
425 bcast_packet->ttl--;
426
427 skb_reset_mac_header(skb);
428
429 forw_packet->skb = skb;
430 forw_packet->if_incoming = bat_priv->primary_if;
431
432 /* how often did we send the bcast packet ? */
433 forw_packet->num_packets = 0;
434
435 _add_bcast_packet_to_list(bat_priv, forw_packet, 1);
436 return NETDEV_TX_OK;
437
438packet_free:
439 kfree(forw_packet);
440out_and_inc:
441 atomic_inc(&bat_priv->bcast_queue_left);
442out:
443 return NETDEV_TX_BUSY;
444}
445
446static void send_outstanding_bcast_packet(struct work_struct *work)
447{
448 struct batman_if *batman_if;
449 struct delayed_work *delayed_work =
450 container_of(work, struct delayed_work, work);
451 struct forw_packet *forw_packet =
452 container_of(delayed_work, struct forw_packet, delayed_work);
453 struct sk_buff *skb1;
454 struct net_device *soft_iface = forw_packet->if_incoming->soft_iface;
455 struct bat_priv *bat_priv = netdev_priv(soft_iface);
456
457 spin_lock_bh(&bat_priv->forw_bcast_list_lock);
458 hlist_del(&forw_packet->list);
459 spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
460
461 if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING)
462 goto out;
463
464 /* rebroadcast packet */
465 rcu_read_lock();
466 list_for_each_entry_rcu(batman_if, &if_list, list) {
467 if (batman_if->soft_iface != soft_iface)
468 continue;
469
470 /* send a copy of the saved skb */
471 skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
472 if (skb1)
473 send_skb_packet(skb1, batman_if, broadcast_addr);
474 }
475 rcu_read_unlock();
476
477 forw_packet->num_packets++;
478
479 /* if we still have some more bcasts to send */
480 if (forw_packet->num_packets < 3) {
481 _add_bcast_packet_to_list(bat_priv, forw_packet,
482 ((5 * HZ) / 1000));
483 return;
484 }
485
486out:
487 forw_packet_free(forw_packet);
488 atomic_inc(&bat_priv->bcast_queue_left);
489}
490
491void send_outstanding_bat_packet(struct work_struct *work)
492{
493 struct delayed_work *delayed_work =
494 container_of(work, struct delayed_work, work);
495 struct forw_packet *forw_packet =
496 container_of(delayed_work, struct forw_packet, delayed_work);
497 struct bat_priv *bat_priv;
498
499 bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
500 spin_lock_bh(&bat_priv->forw_bat_list_lock);
501 hlist_del(&forw_packet->list);
502 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
503
504 if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING)
505 goto out;
506
507 send_packet(forw_packet);
508
509 /**
510 * we have to have at least one packet in the queue
511 * to determine the queues wake up time unless we are
512 * shutting down
513 */
514 if (forw_packet->own)
515 schedule_own_packet(forw_packet->if_incoming);
516
517out:
518 /* don't count own packet */
519 if (!forw_packet->own)
520 atomic_inc(&bat_priv->batman_queue_left);
521
522 forw_packet_free(forw_packet);
523}
524
525void purge_outstanding_packets(struct bat_priv *bat_priv,
526 struct batman_if *batman_if)
527{
528 struct forw_packet *forw_packet;
529 struct hlist_node *tmp_node, *safe_tmp_node;
530
531 if (batman_if)
532 bat_dbg(DBG_BATMAN, bat_priv,
533 "purge_outstanding_packets(): %s\n",
534 batman_if->net_dev->name);
535 else
536 bat_dbg(DBG_BATMAN, bat_priv,
537 "purge_outstanding_packets()\n");
538
539 /* free bcast list */
540 spin_lock_bh(&bat_priv->forw_bcast_list_lock);
541 hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
542 &bat_priv->forw_bcast_list, list) {
543
544 /**
545 * if purge_outstanding_packets() was called with an argmument
546 * we delete only packets belonging to the given interface
547 */
548 if ((batman_if) &&
549 (forw_packet->if_incoming != batman_if))
550 continue;
551
552 spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
553
554 /**
555 * send_outstanding_bcast_packet() will lock the list to
556 * delete the item from the list
557 */
558 cancel_delayed_work_sync(&forw_packet->delayed_work);
559 spin_lock_bh(&bat_priv->forw_bcast_list_lock);
560 }
561 spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
562
563 /* free batman packet list */
564 spin_lock_bh(&bat_priv->forw_bat_list_lock);
565 hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
566 &bat_priv->forw_bat_list, list) {
567
568 /**
569 * if purge_outstanding_packets() was called with an argmument
570 * we delete only packets belonging to the given interface
571 */
572 if ((batman_if) &&
573 (forw_packet->if_incoming != batman_if))
574 continue;
575
576 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
577
578 /**
579 * send_outstanding_bat_packet() will lock the list to
580 * delete the item from the list
581 */
582 cancel_delayed_work_sync(&forw_packet->delayed_work);
583 spin_lock_bh(&bat_priv->forw_bat_list_lock);
584 }
585 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
586}
diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h
deleted file mode 100644
index c4cefa8e4f85..000000000000
--- a/drivers/staging/batman-adv/send.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_SEND_H_
23#define _NET_BATMAN_ADV_SEND_H_
24
25#include "types.h"
26
27int send_skb_packet(struct sk_buff *skb,
28 struct batman_if *batman_if,
29 uint8_t *dst_addr);
30void schedule_own_packet(struct batman_if *batman_if);
31void schedule_forward_packet(struct orig_node *orig_node,
32 struct ethhdr *ethhdr,
33 struct batman_packet *batman_packet,
34 uint8_t directlink, int hna_buff_len,
35 struct batman_if *if_outgoing);
36int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb);
37void send_outstanding_bat_packet(struct work_struct *work);
38void purge_outstanding_packets(struct bat_priv *bat_priv,
39 struct batman_if *batman_if);
40
41#endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c
deleted file mode 100644
index e89ede192ed0..000000000000
--- a/drivers/staging/batman-adv/soft-interface.c
+++ /dev/null
@@ -1,697 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "soft-interface.h"
24#include "hard-interface.h"
25#include "routing.h"
26#include "send.h"
27#include "bat_debugfs.h"
28#include "translation-table.h"
29#include "types.h"
30#include "hash.h"
31#include "gateway_common.h"
32#include "gateway_client.h"
33#include "send.h"
34#include "bat_sysfs.h"
35#include <linux/slab.h>
36#include <linux/ethtool.h>
37#include <linux/etherdevice.h>
38#include <linux/if_vlan.h>
39#include "unicast.h"
40#include "routing.h"
41
42
43static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
44static void bat_get_drvinfo(struct net_device *dev,
45 struct ethtool_drvinfo *info);
46static u32 bat_get_msglevel(struct net_device *dev);
47static void bat_set_msglevel(struct net_device *dev, u32 value);
48static u32 bat_get_link(struct net_device *dev);
49static u32 bat_get_rx_csum(struct net_device *dev);
50static int bat_set_rx_csum(struct net_device *dev, u32 data);
51
52static const struct ethtool_ops bat_ethtool_ops = {
53 .get_settings = bat_get_settings,
54 .get_drvinfo = bat_get_drvinfo,
55 .get_msglevel = bat_get_msglevel,
56 .set_msglevel = bat_set_msglevel,
57 .get_link = bat_get_link,
58 .get_rx_csum = bat_get_rx_csum,
59 .set_rx_csum = bat_set_rx_csum
60};
61
62int my_skb_head_push(struct sk_buff *skb, unsigned int len)
63{
64 int result;
65
66 /**
67 * TODO: We must check if we can release all references to non-payload
68 * data using skb_header_release in our skbs to allow skb_cow_header to
69 * work optimally. This means that those skbs are not allowed to read
70 * or write any data which is before the current position of skb->data
71 * after that call and thus allow other skbs with the same data buffer
72 * to write freely in that area.
73 */
74 result = skb_cow_head(skb, len);
75 if (result < 0)
76 return result;
77
78 skb_push(skb, len);
79 return 0;
80}
81
82static void softif_neigh_free_ref(struct kref *refcount)
83{
84 struct softif_neigh *softif_neigh;
85
86 softif_neigh = container_of(refcount, struct softif_neigh, refcount);
87 kfree(softif_neigh);
88}
89
90static void softif_neigh_free_rcu(struct rcu_head *rcu)
91{
92 struct softif_neigh *softif_neigh;
93
94 softif_neigh = container_of(rcu, struct softif_neigh, rcu);
95 kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
96}
97
98void softif_neigh_purge(struct bat_priv *bat_priv)
99{
100 struct softif_neigh *softif_neigh, *softif_neigh_tmp;
101 struct hlist_node *node, *node_tmp;
102
103 spin_lock_bh(&bat_priv->softif_neigh_lock);
104
105 hlist_for_each_entry_safe(softif_neigh, node, node_tmp,
106 &bat_priv->softif_neigh_list, list) {
107
108 if ((!time_after(jiffies, softif_neigh->last_seen +
109 msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) &&
110 (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
111 continue;
112
113 hlist_del_rcu(&softif_neigh->list);
114
115 if (bat_priv->softif_neigh == softif_neigh) {
116 bat_dbg(DBG_ROUTES, bat_priv,
117 "Current mesh exit point '%pM' vanished "
118 "(vid: %d).\n",
119 softif_neigh->addr, softif_neigh->vid);
120 softif_neigh_tmp = bat_priv->softif_neigh;
121 bat_priv->softif_neigh = NULL;
122 kref_put(&softif_neigh_tmp->refcount,
123 softif_neigh_free_ref);
124 }
125
126 call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
127 }
128
129 spin_unlock_bh(&bat_priv->softif_neigh_lock);
130}
131
132static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
133 uint8_t *addr, short vid)
134{
135 struct softif_neigh *softif_neigh;
136 struct hlist_node *node;
137
138 rcu_read_lock();
139 hlist_for_each_entry_rcu(softif_neigh, node,
140 &bat_priv->softif_neigh_list, list) {
141 if (memcmp(softif_neigh->addr, addr, ETH_ALEN) != 0)
142 continue;
143
144 if (softif_neigh->vid != vid)
145 continue;
146
147 softif_neigh->last_seen = jiffies;
148 goto found;
149 }
150
151 softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
152 if (!softif_neigh)
153 goto out;
154
155 memcpy(softif_neigh->addr, addr, ETH_ALEN);
156 softif_neigh->vid = vid;
157 softif_neigh->last_seen = jiffies;
158 kref_init(&softif_neigh->refcount);
159
160 INIT_HLIST_NODE(&softif_neigh->list);
161 spin_lock_bh(&bat_priv->softif_neigh_lock);
162 hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
163 spin_unlock_bh(&bat_priv->softif_neigh_lock);
164
165found:
166 kref_get(&softif_neigh->refcount);
167out:
168 rcu_read_unlock();
169 return softif_neigh;
170}
171
172int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
173{
174 struct net_device *net_dev = (struct net_device *)seq->private;
175 struct bat_priv *bat_priv = netdev_priv(net_dev);
176 struct softif_neigh *softif_neigh;
177 struct hlist_node *node;
178 size_t buf_size, pos;
179 char *buff;
180
181 if (!bat_priv->primary_if) {
182 return seq_printf(seq, "BATMAN mesh %s disabled - "
183 "please specify interfaces to enable it\n",
184 net_dev->name);
185 }
186
187 seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
188
189 buf_size = 1;
190 /* Estimate length for: " xx:xx:xx:xx:xx:xx\n" */
191 rcu_read_lock();
192 hlist_for_each_entry_rcu(softif_neigh, node,
193 &bat_priv->softif_neigh_list, list)
194 buf_size += 30;
195 rcu_read_unlock();
196
197 buff = kmalloc(buf_size, GFP_ATOMIC);
198 if (!buff)
199 return -ENOMEM;
200
201 buff[0] = '\0';
202 pos = 0;
203
204 rcu_read_lock();
205 hlist_for_each_entry_rcu(softif_neigh, node,
206 &bat_priv->softif_neigh_list, list) {
207 pos += snprintf(buff + pos, 31, "%s %pM (vid: %d)\n",
208 bat_priv->softif_neigh == softif_neigh
209 ? "=>" : " ", softif_neigh->addr,
210 softif_neigh->vid);
211 }
212 rcu_read_unlock();
213
214 seq_printf(seq, "%s", buff);
215 kfree(buff);
216 return 0;
217}
218
219static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
220 short vid)
221{
222 struct bat_priv *bat_priv = netdev_priv(dev);
223 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
224 struct batman_packet *batman_packet;
225 struct softif_neigh *softif_neigh, *softif_neigh_tmp;
226
227 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
228 batman_packet = (struct batman_packet *)
229 (skb->data + ETH_HLEN + VLAN_HLEN);
230 else
231 batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
232
233 if (batman_packet->version != COMPAT_VERSION)
234 goto err;
235
236 if (batman_packet->packet_type != BAT_PACKET)
237 goto err;
238
239 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
240 goto err;
241
242 if (is_my_mac(batman_packet->orig))
243 goto err;
244
245 softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
246
247 if (!softif_neigh)
248 goto err;
249
250 if (bat_priv->softif_neigh == softif_neigh)
251 goto out;
252
253 /* we got a neighbor but its mac is 'bigger' than ours */
254 if (memcmp(bat_priv->primary_if->net_dev->dev_addr,
255 softif_neigh->addr, ETH_ALEN) < 0)
256 goto out;
257
258 /* switch to new 'smallest neighbor' */
259 if ((bat_priv->softif_neigh) &&
260 (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr,
261 ETH_ALEN) < 0)) {
262 bat_dbg(DBG_ROUTES, bat_priv,
263 "Changing mesh exit point from %pM (vid: %d) "
264 "to %pM (vid: %d).\n",
265 bat_priv->softif_neigh->addr,
266 bat_priv->softif_neigh->vid,
267 softif_neigh->addr, softif_neigh->vid);
268 softif_neigh_tmp = bat_priv->softif_neigh;
269 bat_priv->softif_neigh = softif_neigh;
270 kref_put(&softif_neigh_tmp->refcount, softif_neigh_free_ref);
271 /* we need to hold the additional reference */
272 goto err;
273 }
274
275 /* close own batX device and use softif_neigh as exit node */
276 if ((!bat_priv->softif_neigh) &&
277 (memcmp(softif_neigh->addr,
278 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
279 bat_dbg(DBG_ROUTES, bat_priv,
280 "Setting mesh exit point to %pM (vid: %d).\n",
281 softif_neigh->addr, softif_neigh->vid);
282 bat_priv->softif_neigh = softif_neigh;
283 /* we need to hold the additional reference */
284 goto err;
285 }
286
287out:
288 kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
289err:
290 kfree_skb(skb);
291 return;
292}
293
294static int interface_open(struct net_device *dev)
295{
296 netif_start_queue(dev);
297 return 0;
298}
299
300static int interface_release(struct net_device *dev)
301{
302 netif_stop_queue(dev);
303 return 0;
304}
305
306static struct net_device_stats *interface_stats(struct net_device *dev)
307{
308 struct bat_priv *bat_priv = netdev_priv(dev);
309 return &bat_priv->stats;
310}
311
312static int interface_set_mac_addr(struct net_device *dev, void *p)
313{
314 struct bat_priv *bat_priv = netdev_priv(dev);
315 struct sockaddr *addr = p;
316
317 if (!is_valid_ether_addr(addr->sa_data))
318 return -EADDRNOTAVAIL;
319
320 /* only modify hna-table if it has been initialised before */
321 if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
322 hna_local_remove(bat_priv, dev->dev_addr,
323 "mac address changed");
324 hna_local_add(dev, addr->sa_data);
325 }
326
327 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
328 return 0;
329}
330
331static int interface_change_mtu(struct net_device *dev, int new_mtu)
332{
333 /* check ranges */
334 if ((new_mtu < 68) || (new_mtu > hardif_min_mtu(dev)))
335 return -EINVAL;
336
337 dev->mtu = new_mtu;
338
339 return 0;
340}
341
342int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
343{
344 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
345 struct bat_priv *bat_priv = netdev_priv(soft_iface);
346 struct bcast_packet *bcast_packet;
347 struct vlan_ethhdr *vhdr;
348 int data_len = skb->len, ret;
349 short vid = -1;
350 bool do_bcast = false;
351
352 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
353 goto dropped;
354
355 soft_iface->trans_start = jiffies;
356
357 switch (ntohs(ethhdr->h_proto)) {
358 case ETH_P_8021Q:
359 vhdr = (struct vlan_ethhdr *)skb->data;
360 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
361
362 if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
363 break;
364
365 /* fall through */
366 case ETH_P_BATMAN:
367 softif_batman_recv(skb, soft_iface, vid);
368 goto end;
369 }
370
371 /**
372 * if we have a another chosen mesh exit node in range
373 * it will transport the packets to the mesh
374 */
375 if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid))
376 goto dropped;
377
378 /* TODO: check this for locks */
379 hna_local_add(soft_iface, ethhdr->h_source);
380
381 if (is_multicast_ether_addr(ethhdr->h_dest)) {
382 ret = gw_is_target(bat_priv, skb);
383
384 if (ret < 0)
385 goto dropped;
386
387 if (ret == 0)
388 do_bcast = true;
389 }
390
391 /* ethernet packet should be broadcasted */
392 if (do_bcast) {
393 if (!bat_priv->primary_if)
394 goto dropped;
395
396 if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
397 goto dropped;
398
399 bcast_packet = (struct bcast_packet *)skb->data;
400 bcast_packet->version = COMPAT_VERSION;
401 bcast_packet->ttl = TTL;
402
403 /* batman packet type: broadcast */
404 bcast_packet->packet_type = BAT_BCAST;
405
406 /* hw address of first interface is the orig mac because only
407 * this mac is known throughout the mesh */
408 memcpy(bcast_packet->orig,
409 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
410
411 /* set broadcast sequence number */
412 bcast_packet->seqno =
413 htonl(atomic_inc_return(&bat_priv->bcast_seqno));
414
415 add_bcast_packet_to_list(bat_priv, skb);
416
417 /* a copy is stored in the bcast list, therefore removing
418 * the original skb. */
419 kfree_skb(skb);
420
421 /* unicast packet */
422 } else {
423 ret = unicast_send_skb(skb, bat_priv);
424 if (ret != 0)
425 goto dropped_freed;
426 }
427
428 bat_priv->stats.tx_packets++;
429 bat_priv->stats.tx_bytes += data_len;
430 goto end;
431
432dropped:
433 kfree_skb(skb);
434dropped_freed:
435 bat_priv->stats.tx_dropped++;
436end:
437 return NETDEV_TX_OK;
438}
439
440void interface_rx(struct net_device *soft_iface,
441 struct sk_buff *skb, struct batman_if *recv_if,
442 int hdr_size)
443{
444 struct bat_priv *bat_priv = netdev_priv(soft_iface);
445 struct unicast_packet *unicast_packet;
446 struct ethhdr *ethhdr;
447 struct vlan_ethhdr *vhdr;
448 short vid = -1;
449 int ret;
450
451 /* check if enough space is available for pulling, and pull */
452 if (!pskb_may_pull(skb, hdr_size))
453 goto dropped;
454
455 skb_pull_rcsum(skb, hdr_size);
456 skb_reset_mac_header(skb);
457
458 ethhdr = (struct ethhdr *)skb_mac_header(skb);
459
460 switch (ntohs(ethhdr->h_proto)) {
461 case ETH_P_8021Q:
462 vhdr = (struct vlan_ethhdr *)skb->data;
463 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
464
465 if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
466 break;
467
468 /* fall through */
469 case ETH_P_BATMAN:
470 goto dropped;
471 }
472
473 /**
474 * if we have a another chosen mesh exit node in range
475 * it will transport the packets to the non-mesh network
476 */
477 if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) {
478 skb_push(skb, hdr_size);
479 unicast_packet = (struct unicast_packet *)skb->data;
480
481 if ((unicast_packet->packet_type != BAT_UNICAST) &&
482 (unicast_packet->packet_type != BAT_UNICAST_FRAG))
483 goto dropped;
484
485 skb_reset_mac_header(skb);
486
487 memcpy(unicast_packet->dest,
488 bat_priv->softif_neigh->addr, ETH_ALEN);
489 ret = route_unicast_packet(skb, recv_if, hdr_size);
490 if (ret == NET_RX_DROP)
491 goto dropped;
492
493 goto out;
494 }
495
496 /* skb->dev & skb->pkt_type are set here */
497 if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
498 goto dropped;
499 skb->protocol = eth_type_trans(skb, soft_iface);
500
501 /* should not be neccesary anymore as we use skb_pull_rcsum()
502 * TODO: please verify this and remove this TODO
503 * -- Dec 21st 2009, Simon Wunderlich */
504
505/* skb->ip_summed = CHECKSUM_UNNECESSARY;*/
506
507 bat_priv->stats.rx_packets++;
508 bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
509
510 soft_iface->last_rx = jiffies;
511
512 netif_rx(skb);
513 return;
514
515dropped:
516 kfree_skb(skb);
517out:
518 return;
519}
520
521#ifdef HAVE_NET_DEVICE_OPS
522static const struct net_device_ops bat_netdev_ops = {
523 .ndo_open = interface_open,
524 .ndo_stop = interface_release,
525 .ndo_get_stats = interface_stats,
526 .ndo_set_mac_address = interface_set_mac_addr,
527 .ndo_change_mtu = interface_change_mtu,
528 .ndo_start_xmit = interface_tx,
529 .ndo_validate_addr = eth_validate_addr
530};
531#endif
532
533static void interface_setup(struct net_device *dev)
534{
535 struct bat_priv *priv = netdev_priv(dev);
536 char dev_addr[ETH_ALEN];
537
538 ether_setup(dev);
539
540#ifdef HAVE_NET_DEVICE_OPS
541 dev->netdev_ops = &bat_netdev_ops;
542#else
543 dev->open = interface_open;
544 dev->stop = interface_release;
545 dev->get_stats = interface_stats;
546 dev->set_mac_address = interface_set_mac_addr;
547 dev->change_mtu = interface_change_mtu;
548 dev->hard_start_xmit = interface_tx;
549#endif
550 dev->destructor = free_netdev;
551
552 /**
553 * can't call min_mtu, because the needed variables
554 * have not been initialized yet
555 */
556 dev->mtu = ETH_DATA_LEN;
557 dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
558 * skbuff for our header */
559
560 /* generate random address */
561 random_ether_addr(dev_addr);
562 memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
563
564 SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
565
566 memset(priv, 0, sizeof(struct bat_priv));
567}
568
569struct net_device *softif_create(char *name)
570{
571 struct net_device *soft_iface;
572 struct bat_priv *bat_priv;
573 int ret;
574
575 soft_iface = alloc_netdev(sizeof(struct bat_priv) , name,
576 interface_setup);
577
578 if (!soft_iface) {
579 pr_err("Unable to allocate the batman interface: %s\n", name);
580 goto out;
581 }
582
583 ret = register_netdev(soft_iface);
584 if (ret < 0) {
585 pr_err("Unable to register the batman interface '%s': %i\n",
586 name, ret);
587 goto free_soft_iface;
588 }
589
590 bat_priv = netdev_priv(soft_iface);
591
592 atomic_set(&bat_priv->aggregated_ogms, 1);
593 atomic_set(&bat_priv->bonding, 0);
594 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
595 atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
596 atomic_set(&bat_priv->gw_sel_class, 20);
597 atomic_set(&bat_priv->gw_bandwidth, 41);
598 atomic_set(&bat_priv->orig_interval, 1000);
599 atomic_set(&bat_priv->hop_penalty, 10);
600 atomic_set(&bat_priv->log_level, 0);
601 atomic_set(&bat_priv->fragmentation, 1);
602 atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
603 atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
604
605 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
606 atomic_set(&bat_priv->bcast_seqno, 1);
607 atomic_set(&bat_priv->hna_local_changed, 0);
608
609 bat_priv->primary_if = NULL;
610 bat_priv->num_ifaces = 0;
611 bat_priv->softif_neigh = NULL;
612
613 ret = sysfs_add_meshif(soft_iface);
614 if (ret < 0)
615 goto unreg_soft_iface;
616
617 ret = debugfs_add_meshif(soft_iface);
618 if (ret < 0)
619 goto unreg_sysfs;
620
621 ret = mesh_init(soft_iface);
622 if (ret < 0)
623 goto unreg_debugfs;
624
625 return soft_iface;
626
627unreg_debugfs:
628 debugfs_del_meshif(soft_iface);
629unreg_sysfs:
630 sysfs_del_meshif(soft_iface);
631unreg_soft_iface:
632 unregister_netdev(soft_iface);
633 return NULL;
634
635free_soft_iface:
636 free_netdev(soft_iface);
637out:
638 return NULL;
639}
640
641void softif_destroy(struct net_device *soft_iface)
642{
643 debugfs_del_meshif(soft_iface);
644 sysfs_del_meshif(soft_iface);
645 mesh_free(soft_iface);
646 unregister_netdevice(soft_iface);
647}
648
649/* ethtool */
650static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
651{
652 cmd->supported = 0;
653 cmd->advertising = 0;
654 cmd->speed = SPEED_10;
655 cmd->duplex = DUPLEX_FULL;
656 cmd->port = PORT_TP;
657 cmd->phy_address = 0;
658 cmd->transceiver = XCVR_INTERNAL;
659 cmd->autoneg = AUTONEG_DISABLE;
660 cmd->maxtxpkt = 0;
661 cmd->maxrxpkt = 0;
662
663 return 0;
664}
665
666static void bat_get_drvinfo(struct net_device *dev,
667 struct ethtool_drvinfo *info)
668{
669 strcpy(info->driver, "B.A.T.M.A.N. advanced");
670 strcpy(info->version, SOURCE_VERSION);
671 strcpy(info->fw_version, "N/A");
672 strcpy(info->bus_info, "batman");
673}
674
675static u32 bat_get_msglevel(struct net_device *dev)
676{
677 return -EOPNOTSUPP;
678}
679
680static void bat_set_msglevel(struct net_device *dev, u32 value)
681{
682}
683
684static u32 bat_get_link(struct net_device *dev)
685{
686 return 1;
687}
688
689static u32 bat_get_rx_csum(struct net_device *dev)
690{
691 return 0;
692}
693
694static int bat_set_rx_csum(struct net_device *dev, u32 data)
695{
696 return -EOPNOTSUPP;
697}
diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h
deleted file mode 100644
index 02b77334d10d..000000000000
--- a/drivers/staging/batman-adv/soft-interface.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_SOFT_INTERFACE_H_
23#define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
24
25int my_skb_head_push(struct sk_buff *skb, unsigned int len);
26int softif_neigh_seq_print_text(struct seq_file *seq, void *offset);
27void softif_neigh_purge(struct bat_priv *bat_priv);
28int interface_tx(struct sk_buff *skb, struct net_device *soft_iface);
29void interface_rx(struct net_device *soft_iface,
30 struct sk_buff *skb, struct batman_if *recv_if,
31 int hdr_size);
32struct net_device *softif_create(char *name);
33void softif_destroy(struct net_device *soft_iface);
34
35#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/drivers/staging/batman-adv/sysfs-class-net-batman-adv b/drivers/staging/batman-adv/sysfs-class-net-batman-adv
deleted file mode 100644
index 38dd762def4b..000000000000
--- a/drivers/staging/batman-adv/sysfs-class-net-batman-adv
+++ /dev/null
@@ -1,14 +0,0 @@
1
2What: /sys/class/net/<iface>/batman-adv/mesh_iface
3Date: May 2010
4Contact: Marek Lindner <lindner_marek@yahoo.de>
5Description:
6 The /sys/class/net/<iface>/batman-adv/mesh_iface file
7 displays the batman mesh interface this <iface>
8 currently is associated with.
9
10What: /sys/class/net/<iface>/batman-adv/iface_status
11Date: May 2010
12Contact: Marek Lindner <lindner_marek@yahoo.de>
13Description:
14 Indicates the status of <iface> as it is seen by batman.
diff --git a/drivers/staging/batman-adv/sysfs-class-net-mesh b/drivers/staging/batman-adv/sysfs-class-net-mesh
deleted file mode 100644
index 748fe1701d25..000000000000
--- a/drivers/staging/batman-adv/sysfs-class-net-mesh
+++ /dev/null
@@ -1,69 +0,0 @@
1
2What: /sys/class/net/<mesh_iface>/mesh/aggregated_ogms
3Date: May 2010
4Contact: Marek Lindner <lindner_marek@yahoo.de>
5Description:
6 Indicates whether the batman protocol messages of the
7 mesh <mesh_iface> shall be aggregated or not.
8
9What: /sys/class/net/<mesh_iface>/mesh/bonding
10Date: June 2010
11Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
12Description:
13 Indicates whether the data traffic going through the
14 mesh will be sent using multiple interfaces at the
15 same time (if available).
16
17What: /sys/class/net/<mesh_iface>/mesh/fragmentation
18Date: October 2010
19Contact: Andreas Langer <an.langer@gmx.de>
20Description:
21 Indicates whether the data traffic going through the
22 mesh will be fragmented or silently discarded if the
23 packet size exceeds the outgoing interface MTU.
24
25What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
26Date: October 2010
27Contact: Marek Lindner <lindner_marek@yahoo.de>
28Description:
29 Defines the bandwidth which is propagated by this
30 node if gw_mode was set to 'server'.
31
32What: /sys/class/net/<mesh_iface>/mesh/gw_mode
33Date: October 2010
34Contact: Marek Lindner <lindner_marek@yahoo.de>
35Description:
36 Defines the state of the gateway features. Can be
37 either 'off', 'client' or 'server'.
38
39What: /sys/class/net/<mesh_iface>/mesh/gw_sel_class
40Date: October 2010
41Contact: Marek Lindner <lindner_marek@yahoo.de>
42Description:
43 Defines the selection criteria this node will use
44 to choose a gateway if gw_mode was set to 'client'.
45
46What: /sys/class/net/<mesh_iface>/mesh/orig_interval
47Date: May 2010
48Contact: Marek Lindner <lindner_marek@yahoo.de>
49Description:
50 Defines the interval in milliseconds in which batman
51 sends its protocol messages.
52
53What: /sys/class/net/<mesh_iface>/mesh/hop_penalty
54Date: Oct 2010
55Contact: Linus Lüssing <linus.luessing@web.de>
56Description:
57 Defines the penalty which will be applied to an
58 originator message's tq-field on every hop.
59
60What: /sys/class/net/<mesh_iface>/mesh/vis_mode
61Date: May 2010
62Contact: Marek Lindner <lindner_marek@yahoo.de>
63Description:
64 Each batman node only maintains information about its
65 own local neighborhood, therefore generating graphs
66 showing the topology of the entire mesh is not easily
67 feasible without having a central instance to collect
68 the local topologies from all nodes. This file allows
69 to activate the collecting (server) mode.
diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c
deleted file mode 100644
index 4b0a1079347b..000000000000
--- a/drivers/staging/batman-adv/translation-table.c
+++ /dev/null
@@ -1,528 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "translation-table.h"
24#include "soft-interface.h"
25#include "types.h"
26#include "hash.h"
27#include "originator.h"
28
29static void hna_local_purge(struct work_struct *work);
30static void _hna_global_del_orig(struct bat_priv *bat_priv,
31 struct hna_global_entry *hna_global_entry,
32 char *message);
33
34static void hna_local_start_timer(struct bat_priv *bat_priv)
35{
36 INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge);
37 queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ);
38}
39
40int hna_local_init(struct bat_priv *bat_priv)
41{
42 if (bat_priv->hna_local_hash)
43 return 1;
44
45 bat_priv->hna_local_hash = hash_new(128);
46
47 if (!bat_priv->hna_local_hash)
48 return 0;
49
50 atomic_set(&bat_priv->hna_local_changed, 0);
51 hna_local_start_timer(bat_priv);
52
53 return 1;
54}
55
56void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
57{
58 struct bat_priv *bat_priv = netdev_priv(soft_iface);
59 struct hna_local_entry *hna_local_entry;
60 struct hna_global_entry *hna_global_entry;
61 struct hashtable_t *swaphash;
62 int required_bytes;
63
64 spin_lock_bh(&bat_priv->hna_lhash_lock);
65 hna_local_entry =
66 ((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash,
67 compare_orig, choose_orig,
68 addr));
69 spin_unlock_bh(&bat_priv->hna_lhash_lock);
70
71 if (hna_local_entry) {
72 hna_local_entry->last_seen = jiffies;
73 return;
74 }
75
76 /* only announce as many hosts as possible in the batman-packet and
77 space in batman_packet->num_hna That also should give a limit to
78 MAC-flooding. */
79 required_bytes = (bat_priv->num_local_hna + 1) * ETH_ALEN;
80 required_bytes += BAT_PACKET_LEN;
81
82 if ((required_bytes > ETH_DATA_LEN) ||
83 (atomic_read(&bat_priv->aggregated_ogms) &&
84 required_bytes > MAX_AGGREGATION_BYTES) ||
85 (bat_priv->num_local_hna + 1 > 255)) {
86 bat_dbg(DBG_ROUTES, bat_priv,
87 "Can't add new local hna entry (%pM): "
88 "number of local hna entries exceeds packet size\n",
89 addr);
90 return;
91 }
92
93 bat_dbg(DBG_ROUTES, bat_priv,
94 "Creating new local hna entry: %pM\n", addr);
95
96 hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
97 if (!hna_local_entry)
98 return;
99
100 memcpy(hna_local_entry->addr, addr, ETH_ALEN);
101 hna_local_entry->last_seen = jiffies;
102
103 /* the batman interface mac address should never be purged */
104 if (compare_orig(addr, soft_iface->dev_addr))
105 hna_local_entry->never_purge = 1;
106 else
107 hna_local_entry->never_purge = 0;
108
109 spin_lock_bh(&bat_priv->hna_lhash_lock);
110
111 hash_add(bat_priv->hna_local_hash, compare_orig, choose_orig,
112 hna_local_entry);
113 bat_priv->num_local_hna++;
114 atomic_set(&bat_priv->hna_local_changed, 1);
115
116 if (bat_priv->hna_local_hash->elements * 4 >
117 bat_priv->hna_local_hash->size) {
118 swaphash = hash_resize(bat_priv->hna_local_hash, choose_orig,
119 bat_priv->hna_local_hash->size * 2);
120
121 if (!swaphash)
122 pr_err("Couldn't resize local hna hash table\n");
123 else
124 bat_priv->hna_local_hash = swaphash;
125 }
126
127 spin_unlock_bh(&bat_priv->hna_lhash_lock);
128
129 /* remove address from global hash if present */
130 spin_lock_bh(&bat_priv->hna_ghash_lock);
131
132 hna_global_entry = ((struct hna_global_entry *)
133 hash_find(bat_priv->hna_global_hash,
134 compare_orig, choose_orig, addr));
135
136 if (hna_global_entry)
137 _hna_global_del_orig(bat_priv, hna_global_entry,
138 "local hna received");
139
140 spin_unlock_bh(&bat_priv->hna_ghash_lock);
141}
142
143int hna_local_fill_buffer(struct bat_priv *bat_priv,
144 unsigned char *buff, int buff_len)
145{
146 struct hna_local_entry *hna_local_entry;
147 struct element_t *bucket;
148 HASHIT(hashit);
149 int i = 0;
150
151 spin_lock_bh(&bat_priv->hna_lhash_lock);
152
153 while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
154
155 if (buff_len < (i + 1) * ETH_ALEN)
156 break;
157
158 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
159 hna_local_entry = bucket->data;
160 memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
161
162 i++;
163 }
164
165 /* if we did not get all new local hnas see you next time ;-) */
166 if (i == bat_priv->num_local_hna)
167 atomic_set(&bat_priv->hna_local_changed, 0);
168
169 spin_unlock_bh(&bat_priv->hna_lhash_lock);
170 return i;
171}
172
173int hna_local_seq_print_text(struct seq_file *seq, void *offset)
174{
175 struct net_device *net_dev = (struct net_device *)seq->private;
176 struct bat_priv *bat_priv = netdev_priv(net_dev);
177 struct hna_local_entry *hna_local_entry;
178 HASHIT(hashit);
179 HASHIT(hashit_count);
180 struct element_t *bucket;
181 size_t buf_size, pos;
182 char *buff;
183
184 if (!bat_priv->primary_if) {
185 return seq_printf(seq, "BATMAN mesh %s disabled - "
186 "please specify interfaces to enable it\n",
187 net_dev->name);
188 }
189
190 seq_printf(seq, "Locally retrieved addresses (from %s) "
191 "announced via HNA:\n",
192 net_dev->name);
193
194 spin_lock_bh(&bat_priv->hna_lhash_lock);
195
196 buf_size = 1;
197 /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
198 while (hash_iterate(bat_priv->hna_local_hash, &hashit_count))
199 buf_size += 21;
200
201 buff = kmalloc(buf_size, GFP_ATOMIC);
202 if (!buff) {
203 spin_unlock_bh(&bat_priv->hna_lhash_lock);
204 return -ENOMEM;
205 }
206 buff[0] = '\0';
207 pos = 0;
208
209 while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
210 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
211 hna_local_entry = bucket->data;
212
213 pos += snprintf(buff + pos, 22, " * %pM\n",
214 hna_local_entry->addr);
215 }
216
217 spin_unlock_bh(&bat_priv->hna_lhash_lock);
218
219 seq_printf(seq, "%s", buff);
220 kfree(buff);
221 return 0;
222}
223
224static void _hna_local_del(void *data, void *arg)
225{
226 struct bat_priv *bat_priv = (struct bat_priv *)arg;
227
228 kfree(data);
229 bat_priv->num_local_hna--;
230 atomic_set(&bat_priv->hna_local_changed, 1);
231}
232
233static void hna_local_del(struct bat_priv *bat_priv,
234 struct hna_local_entry *hna_local_entry,
235 char *message)
236{
237 bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
238 hna_local_entry->addr, message);
239
240 hash_remove(bat_priv->hna_local_hash, compare_orig, choose_orig,
241 hna_local_entry->addr);
242 _hna_local_del(hna_local_entry, bat_priv);
243}
244
245void hna_local_remove(struct bat_priv *bat_priv,
246 uint8_t *addr, char *message)
247{
248 struct hna_local_entry *hna_local_entry;
249
250 spin_lock_bh(&bat_priv->hna_lhash_lock);
251
252 hna_local_entry = (struct hna_local_entry *)
253 hash_find(bat_priv->hna_local_hash, compare_orig, choose_orig,
254 addr);
255 if (hna_local_entry)
256 hna_local_del(bat_priv, hna_local_entry, message);
257
258 spin_unlock_bh(&bat_priv->hna_lhash_lock);
259}
260
261static void hna_local_purge(struct work_struct *work)
262{
263 struct delayed_work *delayed_work =
264 container_of(work, struct delayed_work, work);
265 struct bat_priv *bat_priv =
266 container_of(delayed_work, struct bat_priv, hna_work);
267 struct hna_local_entry *hna_local_entry;
268 HASHIT(hashit);
269 struct element_t *bucket;
270 unsigned long timeout;
271
272 spin_lock_bh(&bat_priv->hna_lhash_lock);
273
274 while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
275 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
276 hna_local_entry = bucket->data;
277
278 timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;
279
280 if ((!hna_local_entry->never_purge) &&
281 time_after(jiffies, timeout))
282 hna_local_del(bat_priv, hna_local_entry,
283 "address timed out");
284 }
285
286 spin_unlock_bh(&bat_priv->hna_lhash_lock);
287 hna_local_start_timer(bat_priv);
288}
289
290void hna_local_free(struct bat_priv *bat_priv)
291{
292 if (!bat_priv->hna_local_hash)
293 return;
294
295 cancel_delayed_work_sync(&bat_priv->hna_work);
296 hash_delete(bat_priv->hna_local_hash, _hna_local_del, bat_priv);
297 bat_priv->hna_local_hash = NULL;
298}
299
300int hna_global_init(struct bat_priv *bat_priv)
301{
302 if (bat_priv->hna_global_hash)
303 return 1;
304
305 bat_priv->hna_global_hash = hash_new(128);
306
307 if (!bat_priv->hna_global_hash)
308 return 0;
309
310 return 1;
311}
312
313void hna_global_add_orig(struct bat_priv *bat_priv,
314 struct orig_node *orig_node,
315 unsigned char *hna_buff, int hna_buff_len)
316{
317 struct hna_global_entry *hna_global_entry;
318 struct hna_local_entry *hna_local_entry;
319 struct hashtable_t *swaphash;
320 int hna_buff_count = 0;
321 unsigned char *hna_ptr;
322
323 while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) {
324 spin_lock_bh(&bat_priv->hna_ghash_lock);
325
326 hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
327 hna_global_entry = (struct hna_global_entry *)
328 hash_find(bat_priv->hna_global_hash, compare_orig,
329 choose_orig, hna_ptr);
330
331 if (!hna_global_entry) {
332 spin_unlock_bh(&bat_priv->hna_ghash_lock);
333
334 hna_global_entry =
335 kmalloc(sizeof(struct hna_global_entry),
336 GFP_ATOMIC);
337
338 if (!hna_global_entry)
339 break;
340
341 memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
342
343 bat_dbg(DBG_ROUTES, bat_priv,
344 "Creating new global hna entry: "
345 "%pM (via %pM)\n",
346 hna_global_entry->addr, orig_node->orig);
347
348 spin_lock_bh(&bat_priv->hna_ghash_lock);
349 hash_add(bat_priv->hna_global_hash, compare_orig,
350 choose_orig, hna_global_entry);
351
352 }
353
354 hna_global_entry->orig_node = orig_node;
355 spin_unlock_bh(&bat_priv->hna_ghash_lock);
356
357 /* remove address from local hash if present */
358 spin_lock_bh(&bat_priv->hna_lhash_lock);
359
360 hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
361 hna_local_entry = (struct hna_local_entry *)
362 hash_find(bat_priv->hna_local_hash, compare_orig,
363 choose_orig, hna_ptr);
364
365 if (hna_local_entry)
366 hna_local_del(bat_priv, hna_local_entry,
367 "global hna received");
368
369 spin_unlock_bh(&bat_priv->hna_lhash_lock);
370
371 hna_buff_count++;
372 }
373
374 /* initialize, and overwrite if malloc succeeds */
375 orig_node->hna_buff = NULL;
376 orig_node->hna_buff_len = 0;
377
378 if (hna_buff_len > 0) {
379 orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC);
380 if (orig_node->hna_buff) {
381 memcpy(orig_node->hna_buff, hna_buff, hna_buff_len);
382 orig_node->hna_buff_len = hna_buff_len;
383 }
384 }
385
386 spin_lock_bh(&bat_priv->hna_ghash_lock);
387
388 if (bat_priv->hna_global_hash->elements * 4 >
389 bat_priv->hna_global_hash->size) {
390 swaphash = hash_resize(bat_priv->hna_global_hash, choose_orig,
391 bat_priv->hna_global_hash->size * 2);
392
393 if (!swaphash)
394 pr_err("Couldn't resize global hna hash table\n");
395 else
396 bat_priv->hna_global_hash = swaphash;
397 }
398
399 spin_unlock_bh(&bat_priv->hna_ghash_lock);
400}
401
402int hna_global_seq_print_text(struct seq_file *seq, void *offset)
403{
404 struct net_device *net_dev = (struct net_device *)seq->private;
405 struct bat_priv *bat_priv = netdev_priv(net_dev);
406 struct hna_global_entry *hna_global_entry;
407 HASHIT(hashit);
408 HASHIT(hashit_count);
409 struct element_t *bucket;
410 size_t buf_size, pos;
411 char *buff;
412
413 if (!bat_priv->primary_if) {
414 return seq_printf(seq, "BATMAN mesh %s disabled - "
415 "please specify interfaces to enable it\n",
416 net_dev->name);
417 }
418
419 seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
420 net_dev->name);
421
422 spin_lock_bh(&bat_priv->hna_ghash_lock);
423
424 buf_size = 1;
425 /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
426 while (hash_iterate(bat_priv->hna_global_hash, &hashit_count))
427 buf_size += 43;
428
429 buff = kmalloc(buf_size, GFP_ATOMIC);
430 if (!buff) {
431 spin_unlock_bh(&bat_priv->hna_ghash_lock);
432 return -ENOMEM;
433 }
434 buff[0] = '\0';
435 pos = 0;
436
437 while (hash_iterate(bat_priv->hna_global_hash, &hashit)) {
438 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
439 hna_global_entry = bucket->data;
440
441 pos += snprintf(buff + pos, 44,
442 " * %pM via %pM\n", hna_global_entry->addr,
443 hna_global_entry->orig_node->orig);
444 }
445
446 spin_unlock_bh(&bat_priv->hna_ghash_lock);
447
448 seq_printf(seq, "%s", buff);
449 kfree(buff);
450 return 0;
451}
452
453static void _hna_global_del_orig(struct bat_priv *bat_priv,
454 struct hna_global_entry *hna_global_entry,
455 char *message)
456{
457 bat_dbg(DBG_ROUTES, bat_priv,
458 "Deleting global hna entry %pM (via %pM): %s\n",
459 hna_global_entry->addr, hna_global_entry->orig_node->orig,
460 message);
461
462 hash_remove(bat_priv->hna_global_hash, compare_orig, choose_orig,
463 hna_global_entry->addr);
464 kfree(hna_global_entry);
465}
466
467void hna_global_del_orig(struct bat_priv *bat_priv,
468 struct orig_node *orig_node, char *message)
469{
470 struct hna_global_entry *hna_global_entry;
471 int hna_buff_count = 0;
472 unsigned char *hna_ptr;
473
474 if (orig_node->hna_buff_len == 0)
475 return;
476
477 spin_lock_bh(&bat_priv->hna_ghash_lock);
478
479 while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
480 hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
481 hna_global_entry = (struct hna_global_entry *)
482 hash_find(bat_priv->hna_global_hash, compare_orig,
483 choose_orig, hna_ptr);
484
485 if ((hna_global_entry) &&
486 (hna_global_entry->orig_node == orig_node))
487 _hna_global_del_orig(bat_priv, hna_global_entry,
488 message);
489
490 hna_buff_count++;
491 }
492
493 spin_unlock_bh(&bat_priv->hna_ghash_lock);
494
495 orig_node->hna_buff_len = 0;
496 kfree(orig_node->hna_buff);
497 orig_node->hna_buff = NULL;
498}
499
500static void hna_global_del(void *data, void *arg)
501{
502 kfree(data);
503}
504
505void hna_global_free(struct bat_priv *bat_priv)
506{
507 if (!bat_priv->hna_global_hash)
508 return;
509
510 hash_delete(bat_priv->hna_global_hash, hna_global_del, NULL);
511 bat_priv->hna_global_hash = NULL;
512}
513
514struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
515{
516 struct hna_global_entry *hna_global_entry;
517
518 spin_lock_bh(&bat_priv->hna_ghash_lock);
519 hna_global_entry = (struct hna_global_entry *)
520 hash_find(bat_priv->hna_global_hash,
521 compare_orig, choose_orig, addr);
522 spin_unlock_bh(&bat_priv->hna_ghash_lock);
523
524 if (!hna_global_entry)
525 return NULL;
526
527 return hna_global_entry->orig_node;
528}
diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h
deleted file mode 100644
index 10c4c5c319b6..000000000000
--- a/drivers/staging/batman-adv/translation-table.h
+++ /dev/null
@@ -1,45 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
23#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
24
25#include "types.h"
26
27int hna_local_init(struct bat_priv *bat_priv);
28void hna_local_add(struct net_device *soft_iface, uint8_t *addr);
29void hna_local_remove(struct bat_priv *bat_priv,
30 uint8_t *addr, char *message);
31int hna_local_fill_buffer(struct bat_priv *bat_priv,
32 unsigned char *buff, int buff_len);
33int hna_local_seq_print_text(struct seq_file *seq, void *offset);
34void hna_local_free(struct bat_priv *bat_priv);
35int hna_global_init(struct bat_priv *bat_priv);
36void hna_global_add_orig(struct bat_priv *bat_priv,
37 struct orig_node *orig_node,
38 unsigned char *hna_buff, int hna_buff_len);
39int hna_global_seq_print_text(struct seq_file *seq, void *offset);
40void hna_global_del_orig(struct bat_priv *bat_priv,
41 struct orig_node *orig_node, char *message);
42void hna_global_free(struct bat_priv *bat_priv);
43struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr);
44
45#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h
deleted file mode 100644
index 1d0084995c7c..000000000000
--- a/drivers/staging/batman-adv/types.h
+++ /dev/null
@@ -1,271 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22
23
24#ifndef _NET_BATMAN_ADV_TYPES_H_
25#define _NET_BATMAN_ADV_TYPES_H_
26
27#include "packet.h"
28#include "bitarray.h"
29
30#define BAT_HEADER_LEN (sizeof(struct ethhdr) + \
31 ((sizeof(struct unicast_packet) > sizeof(struct bcast_packet) ? \
32 sizeof(struct unicast_packet) : \
33 sizeof(struct bcast_packet))))
34
35
36struct batman_if {
37 struct list_head list;
38 int16_t if_num;
39 char if_status;
40 struct net_device *net_dev;
41 atomic_t seqno;
42 atomic_t frag_seqno;
43 unsigned char *packet_buff;
44 int packet_len;
45 struct kobject *hardif_obj;
46 struct kref refcount;
47 struct packet_type batman_adv_ptype;
48 struct net_device *soft_iface;
49 struct rcu_head rcu;
50};
51
52/**
53 * orig_node - structure for orig_list maintaining nodes of mesh
54 * @primary_addr: hosts primary interface address
55 * @last_valid: when last packet from this node was received
56 * @bcast_seqno_reset: time when the broadcast seqno window was reset
57 * @batman_seqno_reset: time when the batman seqno window was reset
58 * @gw_flags: flags related to gateway class
59 * @flags: for now only VIS_SERVER flag
60 * @last_real_seqno: last and best known squence number
61 * @last_ttl: ttl of last received packet
62 * @last_bcast_seqno: last broadcast sequence number received by this host
63 *
64 * @candidates: how many candidates are available
65 * @selected: next bonding candidate
66 */
67struct orig_node {
68 uint8_t orig[ETH_ALEN];
69 uint8_t primary_addr[ETH_ALEN];
70 struct neigh_node *router;
71 TYPE_OF_WORD *bcast_own;
72 uint8_t *bcast_own_sum;
73 uint8_t tq_own;
74 int tq_asym_penalty;
75 unsigned long last_valid;
76 unsigned long bcast_seqno_reset;
77 unsigned long batman_seqno_reset;
78 uint8_t gw_flags;
79 uint8_t flags;
80 unsigned char *hna_buff;
81 int16_t hna_buff_len;
82 uint32_t last_real_seqno;
83 uint8_t last_ttl;
84 TYPE_OF_WORD bcast_bits[NUM_WORDS];
85 uint32_t last_bcast_seqno;
86 struct list_head neigh_list;
87 struct list_head frag_list;
88 unsigned long last_frag_packet;
89 struct {
90 uint8_t candidates;
91 struct neigh_node *selected;
92 } bond;
93};
94
95struct gw_node {
96 struct hlist_node list;
97 struct orig_node *orig_node;
98 unsigned long deleted;
99 struct kref refcount;
100 struct rcu_head rcu;
101};
102
103/**
104 * neigh_node
105 * @last_valid: when last packet via this neighbor was received
106 */
107struct neigh_node {
108 struct list_head list;
109 uint8_t addr[ETH_ALEN];
110 uint8_t real_packet_count;
111 uint8_t tq_recv[TQ_GLOBAL_WINDOW_SIZE];
112 uint8_t tq_index;
113 uint8_t tq_avg;
114 uint8_t last_ttl;
115 struct neigh_node *next_bond_candidate;
116 unsigned long last_valid;
117 TYPE_OF_WORD real_bits[NUM_WORDS];
118 struct orig_node *orig_node;
119 struct batman_if *if_incoming;
120};
121
122
123struct bat_priv {
124 atomic_t mesh_state;
125 struct net_device_stats stats;
126 atomic_t aggregated_ogms; /* boolean */
127 atomic_t bonding; /* boolean */
128 atomic_t fragmentation; /* boolean */
129 atomic_t vis_mode; /* VIS_TYPE_* */
130 atomic_t gw_mode; /* GW_MODE_* */
131 atomic_t gw_sel_class; /* uint */
132 atomic_t gw_bandwidth; /* gw bandwidth */
133 atomic_t orig_interval; /* uint */
134 atomic_t hop_penalty; /* uint */
135 atomic_t log_level; /* uint */
136 atomic_t bcast_seqno;
137 atomic_t bcast_queue_left;
138 atomic_t batman_queue_left;
139 char num_ifaces;
140 struct hlist_head softif_neigh_list;
141 struct softif_neigh *softif_neigh;
142 struct debug_log *debug_log;
143 struct batman_if *primary_if;
144 struct kobject *mesh_obj;
145 struct dentry *debug_dir;
146 struct hlist_head forw_bat_list;
147 struct hlist_head forw_bcast_list;
148 struct hlist_head gw_list;
149 struct list_head vis_send_list;
150 struct hashtable_t *orig_hash;
151 struct hashtable_t *hna_local_hash;
152 struct hashtable_t *hna_global_hash;
153 struct hashtable_t *vis_hash;
154 spinlock_t orig_hash_lock; /* protects orig_hash */
155 spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
156 spinlock_t forw_bcast_list_lock; /* protects */
157 spinlock_t hna_lhash_lock; /* protects hna_local_hash */
158 spinlock_t hna_ghash_lock; /* protects hna_global_hash */
159 spinlock_t gw_list_lock; /* protects gw_list */
160 spinlock_t vis_hash_lock; /* protects vis_hash */
161 spinlock_t vis_list_lock; /* protects vis_info::recv_list */
162 spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */
163 int16_t num_local_hna;
164 atomic_t hna_local_changed;
165 struct delayed_work hna_work;
166 struct delayed_work orig_work;
167 struct delayed_work vis_work;
168 struct gw_node *curr_gw;
169 struct vis_info *my_vis_info;
170};
171
172struct socket_client {
173 struct list_head queue_list;
174 unsigned int queue_len;
175 unsigned char index;
176 spinlock_t lock; /* protects queue_list, queue_len, index */
177 wait_queue_head_t queue_wait;
178 struct bat_priv *bat_priv;
179};
180
181struct socket_packet {
182 struct list_head list;
183 size_t icmp_len;
184 struct icmp_packet_rr icmp_packet;
185};
186
187struct hna_local_entry {
188 uint8_t addr[ETH_ALEN];
189 unsigned long last_seen;
190 char never_purge;
191};
192
193struct hna_global_entry {
194 uint8_t addr[ETH_ALEN];
195 struct orig_node *orig_node;
196};
197
198/**
199 * forw_packet - structure for forw_list maintaining packets to be
200 * send/forwarded
201 */
202struct forw_packet {
203 struct hlist_node list;
204 unsigned long send_time;
205 uint8_t own;
206 struct sk_buff *skb;
207 uint16_t packet_len;
208 uint32_t direct_link_flags;
209 uint8_t num_packets;
210 struct delayed_work delayed_work;
211 struct batman_if *if_incoming;
212};
213
214/* While scanning for vis-entries of a particular vis-originator
215 * this list collects its interfaces to create a subgraph/cluster
216 * out of them later
217 */
218struct if_list_entry {
219 uint8_t addr[ETH_ALEN];
220 bool primary;
221 struct hlist_node list;
222};
223
224struct debug_log {
225 char log_buff[LOG_BUF_LEN];
226 unsigned long log_start;
227 unsigned long log_end;
228 spinlock_t lock; /* protects log_buff, log_start and log_end */
229 wait_queue_head_t queue_wait;
230};
231
232struct frag_packet_list_entry {
233 struct list_head list;
234 uint16_t seqno;
235 struct sk_buff *skb;
236};
237
238struct vis_info {
239 unsigned long first_seen;
240 struct list_head recv_list;
241 /* list of server-neighbors we received a vis-packet
242 * from. we should not reply to them. */
243 struct list_head send_list;
244 struct kref refcount;
245 struct bat_priv *bat_priv;
246 /* this packet might be part of the vis send queue. */
247 struct sk_buff *skb_packet;
248 /* vis_info may follow here*/
249} __attribute__((packed));
250
251struct vis_info_entry {
252 uint8_t src[ETH_ALEN];
253 uint8_t dest[ETH_ALEN];
254 uint8_t quality; /* quality = 0 means HNA */
255} __attribute__((packed));
256
257struct recvlist_node {
258 struct list_head list;
259 uint8_t mac[ETH_ALEN];
260};
261
262struct softif_neigh {
263 struct hlist_node list;
264 uint8_t addr[ETH_ALEN];
265 unsigned long last_seen;
266 short vid;
267 struct kref refcount;
268 struct rcu_head rcu;
269};
270
271#endif /* _NET_BATMAN_ADV_TYPES_H_ */
diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c
deleted file mode 100644
index dc2e28bed844..000000000000
--- a/drivers/staging/batman-adv/unicast.c
+++ /dev/null
@@ -1,343 +0,0 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Andreas Langer
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "unicast.h"
24#include "send.h"
25#include "soft-interface.h"
26#include "gateway_client.h"
27#include "originator.h"
28#include "hash.h"
29#include "translation-table.h"
30#include "routing.h"
31#include "hard-interface.h"
32
33
34static struct sk_buff *frag_merge_packet(struct list_head *head,
35 struct frag_packet_list_entry *tfp,
36 struct sk_buff *skb)
37{
38 struct unicast_frag_packet *up =
39 (struct unicast_frag_packet *)skb->data;
40 struct sk_buff *tmp_skb;
41 struct unicast_packet *unicast_packet;
42 int hdr_len = sizeof(struct unicast_packet),
43 uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
44
45 /* set skb to the first part and tmp_skb to the second part */
46 if (up->flags & UNI_FRAG_HEAD) {
47 tmp_skb = tfp->skb;
48 } else {
49 tmp_skb = skb;
50 skb = tfp->skb;
51 }
52
53 skb_pull(tmp_skb, sizeof(struct unicast_frag_packet));
54 if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0) {
55 /* free buffered skb, skb will be freed later */
56 kfree_skb(tfp->skb);
57 return NULL;
58 }
59
60 /* move free entry to end */
61 tfp->skb = NULL;
62 tfp->seqno = 0;
63 list_move_tail(&tfp->list, head);
64
65 memcpy(skb_put(skb, tmp_skb->len), tmp_skb->data, tmp_skb->len);
66 kfree_skb(tmp_skb);
67
68 memmove(skb->data + uni_diff, skb->data, hdr_len);
69 unicast_packet = (struct unicast_packet *) skb_pull(skb, uni_diff);
70 unicast_packet->packet_type = BAT_UNICAST;
71
72 return skb;
73}
74
75static void frag_create_entry(struct list_head *head, struct sk_buff *skb)
76{
77 struct frag_packet_list_entry *tfp;
78 struct unicast_frag_packet *up =
79 (struct unicast_frag_packet *)skb->data;
80
81 /* free and oldest packets stand at the end */
82 tfp = list_entry((head)->prev, typeof(*tfp), list);
83 kfree_skb(tfp->skb);
84
85 tfp->seqno = ntohs(up->seqno);
86 tfp->skb = skb;
87 list_move(&tfp->list, head);
88 return;
89}
90
91static int frag_create_buffer(struct list_head *head)
92{
93 int i;
94 struct frag_packet_list_entry *tfp;
95
96 for (i = 0; i < FRAG_BUFFER_SIZE; i++) {
97 tfp = kmalloc(sizeof(struct frag_packet_list_entry),
98 GFP_ATOMIC);
99 if (!tfp) {
100 frag_list_free(head);
101 return -ENOMEM;
102 }
103 tfp->skb = NULL;
104 tfp->seqno = 0;
105 INIT_LIST_HEAD(&tfp->list);
106 list_add(&tfp->list, head);
107 }
108
109 return 0;
110}
111
112static struct frag_packet_list_entry *frag_search_packet(struct list_head *head,
113 struct unicast_frag_packet *up)
114{
115 struct frag_packet_list_entry *tfp;
116 struct unicast_frag_packet *tmp_up = NULL;
117 uint16_t search_seqno;
118
119 if (up->flags & UNI_FRAG_HEAD)
120 search_seqno = ntohs(up->seqno)+1;
121 else
122 search_seqno = ntohs(up->seqno)-1;
123
124 list_for_each_entry(tfp, head, list) {
125
126 if (!tfp->skb)
127 continue;
128
129 if (tfp->seqno == ntohs(up->seqno))
130 goto mov_tail;
131
132 tmp_up = (struct unicast_frag_packet *)tfp->skb->data;
133
134 if (tfp->seqno == search_seqno) {
135
136 if ((tmp_up->flags & UNI_FRAG_HEAD) !=
137 (up->flags & UNI_FRAG_HEAD))
138 return tfp;
139 else
140 goto mov_tail;
141 }
142 }
143 return NULL;
144
145mov_tail:
146 list_move_tail(&tfp->list, head);
147 return NULL;
148}
149
150void frag_list_free(struct list_head *head)
151{
152 struct frag_packet_list_entry *pf, *tmp_pf;
153
154 if (!list_empty(head)) {
155
156 list_for_each_entry_safe(pf, tmp_pf, head, list) {
157 kfree_skb(pf->skb);
158 list_del(&pf->list);
159 kfree(pf);
160 }
161 }
162 return;
163}
164
165/* frag_reassemble_skb():
166 * returns NET_RX_DROP if the operation failed - skb is left intact
167 * returns NET_RX_SUCCESS if the fragment was buffered (skb_new will be NULL)
168 * or the skb could be reassembled (skb_new will point to the new packet and
169 * skb was freed)
170 */
171int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
172 struct sk_buff **new_skb)
173{
174 struct orig_node *orig_node;
175 struct frag_packet_list_entry *tmp_frag_entry;
176 int ret = NET_RX_DROP;
177 struct unicast_frag_packet *unicast_packet =
178 (struct unicast_frag_packet *)skb->data;
179
180 *new_skb = NULL;
181 spin_lock_bh(&bat_priv->orig_hash_lock);
182 orig_node = ((struct orig_node *)
183 hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
184 unicast_packet->orig));
185
186 if (!orig_node) {
187 pr_debug("couldn't find originator in orig_hash\n");
188 goto out;
189 }
190
191 orig_node->last_frag_packet = jiffies;
192
193 if (list_empty(&orig_node->frag_list) &&
194 frag_create_buffer(&orig_node->frag_list)) {
195 pr_debug("couldn't create frag buffer\n");
196 goto out;
197 }
198
199 tmp_frag_entry = frag_search_packet(&orig_node->frag_list,
200 unicast_packet);
201
202 if (!tmp_frag_entry) {
203 frag_create_entry(&orig_node->frag_list, skb);
204 ret = NET_RX_SUCCESS;
205 goto out;
206 }
207
208 *new_skb = frag_merge_packet(&orig_node->frag_list, tmp_frag_entry,
209 skb);
210 /* if not, merge failed */
211 if (*new_skb)
212 ret = NET_RX_SUCCESS;
213out:
214 spin_unlock_bh(&bat_priv->orig_hash_lock);
215
216 return ret;
217}
218
219int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
220 struct batman_if *batman_if, uint8_t dstaddr[])
221{
222 struct unicast_packet tmp_uc, *unicast_packet;
223 struct sk_buff *frag_skb;
224 struct unicast_frag_packet *frag1, *frag2;
225 int uc_hdr_len = sizeof(struct unicast_packet);
226 int ucf_hdr_len = sizeof(struct unicast_frag_packet);
227 int data_len = skb->len;
228
229 if (!bat_priv->primary_if)
230 goto dropped;
231
232 unicast_packet = (struct unicast_packet *) skb->data;
233
234 memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
235 frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
236 skb_split(skb, frag_skb, data_len / 2);
237
238 if (my_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
239 my_skb_head_push(frag_skb, ucf_hdr_len) < 0)
240 goto drop_frag;
241
242 frag1 = (struct unicast_frag_packet *)skb->data;
243 frag2 = (struct unicast_frag_packet *)frag_skb->data;
244
245 memcpy(frag1, &tmp_uc, sizeof(struct unicast_packet));
246
247 frag1->ttl--;
248 frag1->version = COMPAT_VERSION;
249 frag1->packet_type = BAT_UNICAST_FRAG;
250
251 memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
252 memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
253
254 frag1->flags |= UNI_FRAG_HEAD;
255 frag2->flags &= ~UNI_FRAG_HEAD;
256
257 frag1->seqno = htons((uint16_t)atomic_inc_return(
258 &batman_if->frag_seqno));
259 frag2->seqno = htons((uint16_t)atomic_inc_return(
260 &batman_if->frag_seqno));
261
262 send_skb_packet(skb, batman_if, dstaddr);
263 send_skb_packet(frag_skb, batman_if, dstaddr);
264 return NET_RX_SUCCESS;
265
266drop_frag:
267 kfree_skb(frag_skb);
268dropped:
269 kfree_skb(skb);
270 return NET_RX_DROP;
271}
272
273int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
274{
275 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
276 struct unicast_packet *unicast_packet;
277 struct orig_node *orig_node;
278 struct batman_if *batman_if;
279 struct neigh_node *router;
280 int data_len = skb->len;
281 uint8_t dstaddr[6];
282
283 spin_lock_bh(&bat_priv->orig_hash_lock);
284
285 /* get routing information */
286 if (is_multicast_ether_addr(ethhdr->h_dest))
287 orig_node = (struct orig_node *)gw_get_selected(bat_priv);
288 else
289 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
290 compare_orig,
291 choose_orig,
292 ethhdr->h_dest));
293
294 /* check for hna host */
295 if (!orig_node)
296 orig_node = transtable_search(bat_priv, ethhdr->h_dest);
297
298 router = find_router(bat_priv, orig_node, NULL);
299
300 if (!router)
301 goto unlock;
302
303 /* don't lock while sending the packets ... we therefore
304 * copy the required data before sending */
305
306 batman_if = router->if_incoming;
307 memcpy(dstaddr, router->addr, ETH_ALEN);
308
309 spin_unlock_bh(&bat_priv->orig_hash_lock);
310
311 if (batman_if->if_status != IF_ACTIVE)
312 goto dropped;
313
314 if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0)
315 goto dropped;
316
317 unicast_packet = (struct unicast_packet *)skb->data;
318
319 unicast_packet->version = COMPAT_VERSION;
320 /* batman packet type: unicast */
321 unicast_packet->packet_type = BAT_UNICAST;
322 /* set unicast ttl */
323 unicast_packet->ttl = TTL;
324 /* copy the destination for faster routing */
325 memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
326
327 if (atomic_read(&bat_priv->fragmentation) &&
328 data_len + sizeof(struct unicast_packet) >
329 batman_if->net_dev->mtu) {
330 /* send frag skb decreases ttl */
331 unicast_packet->ttl++;
332 return frag_send_skb(skb, bat_priv, batman_if,
333 dstaddr);
334 }
335 send_skb_packet(skb, batman_if, dstaddr);
336 return 0;
337
338unlock:
339 spin_unlock_bh(&bat_priv->orig_hash_lock);
340dropped:
341 kfree_skb(skb);
342 return 1;
343}
diff --git a/drivers/staging/batman-adv/unicast.h b/drivers/staging/batman-adv/unicast.h
deleted file mode 100644
index e32b7867a9a4..000000000000
--- a/drivers/staging/batman-adv/unicast.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Andreas Langer
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_UNICAST_H_
23#define _NET_BATMAN_ADV_UNICAST_H_
24
25#define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */
26#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
27
28int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
29 struct sk_buff **new_skb);
30void frag_list_free(struct list_head *head);
31int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv);
32int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
33 struct batman_if *batman_if, uint8_t dstaddr[]);
34
35#endif /* _NET_BATMAN_ADV_UNICAST_H_ */
diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c
deleted file mode 100644
index 957a08624ff8..000000000000
--- a/drivers/staging/batman-adv/vis.c
+++ /dev/null
@@ -1,903 +0,0 @@
1/*
2 * Copyright (C) 2008-2010 B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "send.h"
24#include "translation-table.h"
25#include "vis.h"
26#include "soft-interface.h"
27#include "hard-interface.h"
28#include "hash.h"
29#include "originator.h"
30
31#define MAX_VIS_PACKET_SIZE 1000
32
33/* Returns the smallest signed integer in two's complement with the sizeof x */
34#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
35
36/* Checks if a sequence number x is a predecessor/successor of y.
37 * they handle overflows/underflows and can correctly check for a
38 * predecessor/successor unless the variable sequence number has grown by
39 * more then 2**(bitwidth(x)-1)-1.
40 * This means that for a uint8_t with the maximum value 255, it would think:
41 * - when adding nothing - it is neither a predecessor nor a successor
42 * - before adding more than 127 to the starting value - it is a predecessor,
43 * - when adding 128 - it is neither a predecessor nor a successor,
44 * - after adding more than 127 to the starting value - it is a successor */
45#define seq_before(x, y) ({typeof(x) _dummy = (x - y); \
46 _dummy > smallest_signed_int(_dummy); })
47#define seq_after(x, y) seq_before(y, x)
48
49static void start_vis_timer(struct bat_priv *bat_priv);
50
51/* free the info */
52static void free_info(struct kref *ref)
53{
54 struct vis_info *info = container_of(ref, struct vis_info, refcount);
55 struct bat_priv *bat_priv = info->bat_priv;
56 struct recvlist_node *entry, *tmp;
57
58 list_del_init(&info->send_list);
59 spin_lock_bh(&bat_priv->vis_list_lock);
60 list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
61 list_del(&entry->list);
62 kfree(entry);
63 }
64
65 spin_unlock_bh(&bat_priv->vis_list_lock);
66 kfree_skb(info->skb_packet);
67}
68
69/* Compare two vis packets, used by the hashing algorithm */
70static int vis_info_cmp(void *data1, void *data2)
71{
72 struct vis_info *d1, *d2;
73 struct vis_packet *p1, *p2;
74 d1 = data1;
75 d2 = data2;
76 p1 = (struct vis_packet *)d1->skb_packet->data;
77 p2 = (struct vis_packet *)d2->skb_packet->data;
78 return compare_orig(p1->vis_orig, p2->vis_orig);
79}
80
81/* hash function to choose an entry in a hash table of given size */
82/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
83static int vis_info_choose(void *data, int size)
84{
85 struct vis_info *vis_info = data;
86 struct vis_packet *packet;
87 unsigned char *key;
88 uint32_t hash = 0;
89 size_t i;
90
91 packet = (struct vis_packet *)vis_info->skb_packet->data;
92 key = packet->vis_orig;
93 for (i = 0; i < ETH_ALEN; i++) {
94 hash += key[i];
95 hash += (hash << 10);
96 hash ^= (hash >> 6);
97 }
98
99 hash += (hash << 3);
100 hash ^= (hash >> 11);
101 hash += (hash << 15);
102
103 return hash % size;
104}
105
106/* insert interface to the list of interfaces of one originator, if it
107 * does not already exist in the list */
108static void vis_data_insert_interface(const uint8_t *interface,
109 struct hlist_head *if_list,
110 bool primary)
111{
112 struct if_list_entry *entry;
113 struct hlist_node *pos;
114
115 hlist_for_each_entry(entry, pos, if_list, list) {
116 if (compare_orig(entry->addr, (void *)interface))
117 return;
118 }
119
120 /* its a new address, add it to the list */
121 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
122 if (!entry)
123 return;
124 memcpy(entry->addr, interface, ETH_ALEN);
125 entry->primary = primary;
126 hlist_add_head(&entry->list, if_list);
127}
128
129static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list)
130{
131 struct if_list_entry *entry;
132 struct hlist_node *pos;
133 size_t len = 0;
134
135 hlist_for_each_entry(entry, pos, if_list, list) {
136 if (entry->primary)
137 len += sprintf(buff + len, "PRIMARY, ");
138 else
139 len += sprintf(buff + len, "SEC %pM, ", entry->addr);
140 }
141
142 return len;
143}
144
145static size_t vis_data_count_prim_sec(struct hlist_head *if_list)
146{
147 struct if_list_entry *entry;
148 struct hlist_node *pos;
149 size_t count = 0;
150
151 hlist_for_each_entry(entry, pos, if_list, list) {
152 if (entry->primary)
153 count += 9;
154 else
155 count += 23;
156 }
157
158 return count;
159}
160
161/* read an entry */
162static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
163 uint8_t *src, bool primary)
164{
165 /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
166 if (primary && entry->quality == 0)
167 return sprintf(buff, "HNA %pM, ", entry->dest);
168 else if (compare_orig(entry->src, src))
169 return sprintf(buff, "TQ %pM %d, ", entry->dest,
170 entry->quality);
171
172 return 0;
173}
174
175int vis_seq_print_text(struct seq_file *seq, void *offset)
176{
177 HASHIT(hashit);
178 HASHIT(hashit_count);
179 struct element_t *bucket;
180 struct vis_info *info;
181 struct vis_packet *packet;
182 struct vis_info_entry *entries;
183 struct net_device *net_dev = (struct net_device *)seq->private;
184 struct bat_priv *bat_priv = netdev_priv(net_dev);
185 HLIST_HEAD(vis_if_list);
186 struct if_list_entry *entry;
187 struct hlist_node *pos, *n;
188 int i;
189 int vis_server = atomic_read(&bat_priv->vis_mode);
190 size_t buff_pos, buf_size;
191 char *buff;
192
193 if ((!bat_priv->primary_if) ||
194 (vis_server == VIS_TYPE_CLIENT_UPDATE))
195 return 0;
196
197 buf_size = 1;
198 /* Estimate length */
199 spin_lock_bh(&bat_priv->vis_hash_lock);
200 while (hash_iterate(bat_priv->vis_hash, &hashit_count)) {
201 bucket = hlist_entry(hashit_count.walk, struct element_t,
202 hlist);
203 info = bucket->data;
204 packet = (struct vis_packet *)info->skb_packet->data;
205 entries = (struct vis_info_entry *)
206 ((char *)packet + sizeof(struct vis_packet));
207
208 for (i = 0; i < packet->entries; i++) {
209 if (entries[i].quality == 0)
210 continue;
211 vis_data_insert_interface(entries[i].src, &vis_if_list,
212 compare_orig(entries[i].src, packet->vis_orig));
213 }
214
215 hlist_for_each_entry(entry, pos, &vis_if_list, list) {
216 buf_size += 18 + 26 * packet->entries;
217
218 /* add primary/secondary records */
219 if (compare_orig(entry->addr, packet->vis_orig))
220 buf_size +=
221 vis_data_count_prim_sec(&vis_if_list);
222
223 buf_size += 1;
224 }
225
226 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
227 hlist_del(&entry->list);
228 kfree(entry);
229 }
230 }
231
232 buff = kmalloc(buf_size, GFP_ATOMIC);
233 if (!buff) {
234 spin_unlock_bh(&bat_priv->vis_hash_lock);
235 return -ENOMEM;
236 }
237 buff[0] = '\0';
238 buff_pos = 0;
239
240 while (hash_iterate(bat_priv->vis_hash, &hashit)) {
241 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
242 info = bucket->data;
243 packet = (struct vis_packet *)info->skb_packet->data;
244 entries = (struct vis_info_entry *)
245 ((char *)packet + sizeof(struct vis_packet));
246
247 for (i = 0; i < packet->entries; i++) {
248 if (entries[i].quality == 0)
249 continue;
250 vis_data_insert_interface(entries[i].src, &vis_if_list,
251 compare_orig(entries[i].src, packet->vis_orig));
252 }
253
254 hlist_for_each_entry(entry, pos, &vis_if_list, list) {
255 buff_pos += sprintf(buff + buff_pos, "%pM,",
256 entry->addr);
257
258 for (i = 0; i < packet->entries; i++)
259 buff_pos += vis_data_read_entry(buff + buff_pos,
260 &entries[i],
261 entry->addr,
262 entry->primary);
263
264 /* add primary/secondary records */
265 if (compare_orig(entry->addr, packet->vis_orig))
266 buff_pos +=
267 vis_data_read_prim_sec(buff + buff_pos,
268 &vis_if_list);
269
270 buff_pos += sprintf(buff + buff_pos, "\n");
271 }
272
273 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
274 hlist_del(&entry->list);
275 kfree(entry);
276 }
277 }
278
279 spin_unlock_bh(&bat_priv->vis_hash_lock);
280
281 seq_printf(seq, "%s", buff);
282 kfree(buff);
283
284 return 0;
285}
286
287/* add the info packet to the send list, if it was not
288 * already linked in. */
289static void send_list_add(struct bat_priv *bat_priv, struct vis_info *info)
290{
291 if (list_empty(&info->send_list)) {
292 kref_get(&info->refcount);
293 list_add_tail(&info->send_list, &bat_priv->vis_send_list);
294 }
295}
296
297/* delete the info packet from the send list, if it was
298 * linked in. */
299static void send_list_del(struct vis_info *info)
300{
301 if (!list_empty(&info->send_list)) {
302 list_del_init(&info->send_list);
303 kref_put(&info->refcount, free_info);
304 }
305}
306
307/* tries to add one entry to the receive list. */
308static void recv_list_add(struct bat_priv *bat_priv,
309 struct list_head *recv_list, char *mac)
310{
311 struct recvlist_node *entry;
312
313 entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC);
314 if (!entry)
315 return;
316
317 memcpy(entry->mac, mac, ETH_ALEN);
318 spin_lock_bh(&bat_priv->vis_list_lock);
319 list_add_tail(&entry->list, recv_list);
320 spin_unlock_bh(&bat_priv->vis_list_lock);
321}
322
323/* returns 1 if this mac is in the recv_list */
324static int recv_list_is_in(struct bat_priv *bat_priv,
325 struct list_head *recv_list, char *mac)
326{
327 struct recvlist_node *entry;
328
329 spin_lock_bh(&bat_priv->vis_list_lock);
330 list_for_each_entry(entry, recv_list, list) {
331 if (memcmp(entry->mac, mac, ETH_ALEN) == 0) {
332 spin_unlock_bh(&bat_priv->vis_list_lock);
333 return 1;
334 }
335 }
336 spin_unlock_bh(&bat_priv->vis_list_lock);
337 return 0;
338}
339
340/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
341 * broken.. ). vis hash must be locked outside. is_new is set when the packet
342 * is newer than old entries in the hash. */
343static struct vis_info *add_packet(struct bat_priv *bat_priv,
344 struct vis_packet *vis_packet,
345 int vis_info_len, int *is_new,
346 int make_broadcast)
347{
348 struct vis_info *info, *old_info;
349 struct vis_packet *search_packet, *old_packet;
350 struct vis_info search_elem;
351 struct vis_packet *packet;
352 int hash_added;
353
354 *is_new = 0;
355 /* sanity check */
356 if (!bat_priv->vis_hash)
357 return NULL;
358
359 /* see if the packet is already in vis_hash */
360 search_elem.skb_packet = dev_alloc_skb(sizeof(struct vis_packet));
361 if (!search_elem.skb_packet)
362 return NULL;
363 search_packet = (struct vis_packet *)skb_put(search_elem.skb_packet,
364 sizeof(struct vis_packet));
365
366 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
367 old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
368 &search_elem);
369 kfree_skb(search_elem.skb_packet);
370
371 if (old_info != NULL) {
372 old_packet = (struct vis_packet *)old_info->skb_packet->data;
373 if (!seq_after(ntohl(vis_packet->seqno),
374 ntohl(old_packet->seqno))) {
375 if (old_packet->seqno == vis_packet->seqno) {
376 recv_list_add(bat_priv, &old_info->recv_list,
377 vis_packet->sender_orig);
378 return old_info;
379 } else {
380 /* newer packet is already in hash. */
381 return NULL;
382 }
383 }
384 /* remove old entry */
385 hash_remove(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
386 old_info);
387 send_list_del(old_info);
388 kref_put(&old_info->refcount, free_info);
389 }
390
391 info = kmalloc(sizeof(struct vis_info), GFP_ATOMIC);
392 if (!info)
393 return NULL;
394
395 info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) +
396 vis_info_len + sizeof(struct ethhdr));
397 if (!info->skb_packet) {
398 kfree(info);
399 return NULL;
400 }
401 skb_reserve(info->skb_packet, sizeof(struct ethhdr));
402 packet = (struct vis_packet *)skb_put(info->skb_packet,
403 sizeof(struct vis_packet) +
404 vis_info_len);
405
406 kref_init(&info->refcount);
407 INIT_LIST_HEAD(&info->send_list);
408 INIT_LIST_HEAD(&info->recv_list);
409 info->first_seen = jiffies;
410 info->bat_priv = bat_priv;
411 memcpy(packet, vis_packet, sizeof(struct vis_packet) + vis_info_len);
412
413 /* initialize and add new packet. */
414 *is_new = 1;
415
416 /* Make it a broadcast packet, if required */
417 if (make_broadcast)
418 memcpy(packet->target_orig, broadcast_addr, ETH_ALEN);
419
420 /* repair if entries is longer than packet. */
421 if (packet->entries * sizeof(struct vis_info_entry) > vis_info_len)
422 packet->entries = vis_info_len / sizeof(struct vis_info_entry);
423
424 recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
425
426 /* try to add it */
427 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
428 info);
429 if (hash_added < 0) {
430 /* did not work (for some reason) */
431 kref_put(&old_info->refcount, free_info);
432 info = NULL;
433 }
434
435 return info;
436}
437
438/* handle the server sync packet, forward if needed. */
439void receive_server_sync_packet(struct bat_priv *bat_priv,
440 struct vis_packet *vis_packet,
441 int vis_info_len)
442{
443 struct vis_info *info;
444 int is_new, make_broadcast;
445 int vis_server = atomic_read(&bat_priv->vis_mode);
446
447 make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC);
448
449 spin_lock_bh(&bat_priv->vis_hash_lock);
450 info = add_packet(bat_priv, vis_packet, vis_info_len,
451 &is_new, make_broadcast);
452 if (!info)
453 goto end;
454
455 /* only if we are server ourselves and packet is newer than the one in
456 * hash.*/
457 if (vis_server == VIS_TYPE_SERVER_SYNC && is_new)
458 send_list_add(bat_priv, info);
459end:
460 spin_unlock_bh(&bat_priv->vis_hash_lock);
461}
462
463/* handle an incoming client update packet and schedule forward if needed. */
464void receive_client_update_packet(struct bat_priv *bat_priv,
465 struct vis_packet *vis_packet,
466 int vis_info_len)
467{
468 struct vis_info *info;
469 struct vis_packet *packet;
470 int is_new;
471 int vis_server = atomic_read(&bat_priv->vis_mode);
472 int are_target = 0;
473
474 /* clients shall not broadcast. */
475 if (is_broadcast_ether_addr(vis_packet->target_orig))
476 return;
477
478 /* Are we the target for this VIS packet? */
479 if (vis_server == VIS_TYPE_SERVER_SYNC &&
480 is_my_mac(vis_packet->target_orig))
481 are_target = 1;
482
483 spin_lock_bh(&bat_priv->vis_hash_lock);
484 info = add_packet(bat_priv, vis_packet, vis_info_len,
485 &is_new, are_target);
486
487 if (!info)
488 goto end;
489 /* note that outdated packets will be dropped at this point. */
490
491 packet = (struct vis_packet *)info->skb_packet->data;
492
493 /* send only if we're the target server or ... */
494 if (are_target && is_new) {
495 packet->vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */
496 send_list_add(bat_priv, info);
497
498 /* ... we're not the recipient (and thus need to forward). */
499 } else if (!is_my_mac(packet->target_orig)) {
500 send_list_add(bat_priv, info);
501 }
502
503end:
504 spin_unlock_bh(&bat_priv->vis_hash_lock);
505}
506
507/* Walk the originators and find the VIS server with the best tq. Set the packet
508 * address to its address and return the best_tq.
509 *
510 * Must be called with the originator hash locked */
511static int find_best_vis_server(struct bat_priv *bat_priv,
512 struct vis_info *info)
513{
514 HASHIT(hashit);
515 struct element_t *bucket;
516 struct orig_node *orig_node;
517 struct vis_packet *packet;
518 int best_tq = -1;
519
520 packet = (struct vis_packet *)info->skb_packet->data;
521
522 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
523 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
524 orig_node = bucket->data;
525 if ((orig_node) && (orig_node->router) &&
526 (orig_node->flags & VIS_SERVER) &&
527 (orig_node->router->tq_avg > best_tq)) {
528 best_tq = orig_node->router->tq_avg;
529 memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
530 }
531 }
532 return best_tq;
533}
534
535/* Return true if the vis packet is full. */
536static bool vis_packet_full(struct vis_info *info)
537{
538 struct vis_packet *packet;
539 packet = (struct vis_packet *)info->skb_packet->data;
540
541 if (MAX_VIS_PACKET_SIZE / sizeof(struct vis_info_entry)
542 < packet->entries + 1)
543 return true;
544 return false;
545}
546
547/* generates a packet of own vis data,
548 * returns 0 on success, -1 if no packet could be generated */
549static int generate_vis_packet(struct bat_priv *bat_priv)
550{
551 HASHIT(hashit_local);
552 HASHIT(hashit_global);
553 struct element_t *bucket;
554 struct orig_node *orig_node;
555 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
556 struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
557 struct vis_info_entry *entry;
558 struct hna_local_entry *hna_local_entry;
559 int best_tq = -1;
560
561 info->first_seen = jiffies;
562 packet->vis_type = atomic_read(&bat_priv->vis_mode);
563
564 spin_lock_bh(&bat_priv->orig_hash_lock);
565 memcpy(packet->target_orig, broadcast_addr, ETH_ALEN);
566 packet->ttl = TTL;
567 packet->seqno = htonl(ntohl(packet->seqno) + 1);
568 packet->entries = 0;
569 skb_trim(info->skb_packet, sizeof(struct vis_packet));
570
571 if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) {
572 best_tq = find_best_vis_server(bat_priv, info);
573
574 if (best_tq < 0) {
575 spin_unlock_bh(&bat_priv->orig_hash_lock);
576 return -1;
577 }
578 }
579
580 while (hash_iterate(bat_priv->orig_hash, &hashit_global)) {
581 bucket = hlist_entry(hashit_global.walk, struct element_t,
582 hlist);
583 orig_node = bucket->data;
584
585 if (!orig_node->router)
586 continue;
587
588 if (!compare_orig(orig_node->router->addr, orig_node->orig))
589 continue;
590
591 if (orig_node->router->if_incoming->if_status != IF_ACTIVE)
592 continue;
593
594 if (orig_node->router->tq_avg < 1)
595 continue;
596
597 /* fill one entry into buffer. */
598 entry = (struct vis_info_entry *)
599 skb_put(info->skb_packet, sizeof(*entry));
600 memcpy(entry->src,
601 orig_node->router->if_incoming->net_dev->dev_addr,
602 ETH_ALEN);
603 memcpy(entry->dest, orig_node->orig, ETH_ALEN);
604 entry->quality = orig_node->router->tq_avg;
605 packet->entries++;
606
607 if (vis_packet_full(info)) {
608 spin_unlock_bh(&bat_priv->orig_hash_lock);
609 return 0;
610 }
611 }
612
613 spin_unlock_bh(&bat_priv->orig_hash_lock);
614
615 spin_lock_bh(&bat_priv->hna_lhash_lock);
616 while (hash_iterate(bat_priv->hna_local_hash, &hashit_local)) {
617 bucket = hlist_entry(hashit_local.walk, struct element_t,
618 hlist);
619 hna_local_entry = bucket->data;
620 entry = (struct vis_info_entry *)skb_put(info->skb_packet,
621 sizeof(*entry));
622 memset(entry->src, 0, ETH_ALEN);
623 memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN);
624 entry->quality = 0; /* 0 means HNA */
625 packet->entries++;
626
627 if (vis_packet_full(info)) {
628 spin_unlock_bh(&bat_priv->hna_lhash_lock);
629 return 0;
630 }
631 }
632
633 spin_unlock_bh(&bat_priv->hna_lhash_lock);
634 return 0;
635}
636
637/* free old vis packets. Must be called with this vis_hash_lock
638 * held */
639static void purge_vis_packets(struct bat_priv *bat_priv)
640{
641 HASHIT(hashit);
642 struct element_t *bucket;
643 struct vis_info *info;
644
645 while (hash_iterate(bat_priv->vis_hash, &hashit)) {
646 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
647 info = bucket->data;
648
649 /* never purge own data. */
650 if (info == bat_priv->my_vis_info)
651 continue;
652
653 if (time_after(jiffies,
654 info->first_seen + VIS_TIMEOUT * HZ)) {
655 hash_remove_bucket(bat_priv->vis_hash, &hashit);
656 send_list_del(info);
657 kref_put(&info->refcount, free_info);
658 }
659 }
660}
661
662static void broadcast_vis_packet(struct bat_priv *bat_priv,
663 struct vis_info *info)
664{
665 HASHIT(hashit);
666 struct element_t *bucket;
667 struct orig_node *orig_node;
668 struct vis_packet *packet;
669 struct sk_buff *skb;
670 struct batman_if *batman_if;
671 uint8_t dstaddr[ETH_ALEN];
672
673
674 spin_lock_bh(&bat_priv->orig_hash_lock);
675 packet = (struct vis_packet *)info->skb_packet->data;
676
677 /* send to all routers in range. */
678 while (hash_iterate(bat_priv->orig_hash, &hashit)) {
679 bucket = hlist_entry(hashit.walk, struct element_t, hlist);
680 orig_node = bucket->data;
681
682 /* if it's a vis server and reachable, send it. */
683 if ((!orig_node) || (!orig_node->router))
684 continue;
685 if (!(orig_node->flags & VIS_SERVER))
686 continue;
687 /* don't send it if we already received the packet from
688 * this node. */
689 if (recv_list_is_in(bat_priv, &info->recv_list,
690 orig_node->orig))
691 continue;
692
693 memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
694 batman_if = orig_node->router->if_incoming;
695 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
696 spin_unlock_bh(&bat_priv->orig_hash_lock);
697
698 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
699 if (skb)
700 send_skb_packet(skb, batman_if, dstaddr);
701
702 spin_lock_bh(&bat_priv->orig_hash_lock);
703
704 }
705
706 spin_unlock_bh(&bat_priv->orig_hash_lock);
707}
708
709static void unicast_vis_packet(struct bat_priv *bat_priv,
710 struct vis_info *info)
711{
712 struct orig_node *orig_node;
713 struct sk_buff *skb;
714 struct vis_packet *packet;
715 struct batman_if *batman_if;
716 uint8_t dstaddr[ETH_ALEN];
717
718 spin_lock_bh(&bat_priv->orig_hash_lock);
719 packet = (struct vis_packet *)info->skb_packet->data;
720 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
721 compare_orig, choose_orig,
722 packet->target_orig));
723
724 if ((!orig_node) || (!orig_node->router))
725 goto out;
726
727 /* don't lock while sending the packets ... we therefore
728 * copy the required data before sending */
729 batman_if = orig_node->router->if_incoming;
730 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
731 spin_unlock_bh(&bat_priv->orig_hash_lock);
732
733 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
734 if (skb)
735 send_skb_packet(skb, batman_if, dstaddr);
736
737 return;
738
739out:
740 spin_unlock_bh(&bat_priv->orig_hash_lock);
741}
742
743/* only send one vis packet. called from send_vis_packets() */
744static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
745{
746 struct vis_packet *packet;
747
748 packet = (struct vis_packet *)info->skb_packet->data;
749 if (packet->ttl < 2) {
750 pr_debug("Error - can't send vis packet: ttl exceeded\n");
751 return;
752 }
753
754 memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr,
755 ETH_ALEN);
756 packet->ttl--;
757
758 if (is_broadcast_ether_addr(packet->target_orig))
759 broadcast_vis_packet(bat_priv, info);
760 else
761 unicast_vis_packet(bat_priv, info);
762 packet->ttl++; /* restore TTL */
763}
764
765/* called from timer; send (and maybe generate) vis packet. */
766static void send_vis_packets(struct work_struct *work)
767{
768 struct delayed_work *delayed_work =
769 container_of(work, struct delayed_work, work);
770 struct bat_priv *bat_priv =
771 container_of(delayed_work, struct bat_priv, vis_work);
772 struct vis_info *info, *temp;
773
774 spin_lock_bh(&bat_priv->vis_hash_lock);
775 purge_vis_packets(bat_priv);
776
777 if (generate_vis_packet(bat_priv) == 0) {
778 /* schedule if generation was successful */
779 send_list_add(bat_priv, bat_priv->my_vis_info);
780 }
781
782 list_for_each_entry_safe(info, temp, &bat_priv->vis_send_list,
783 send_list) {
784
785 kref_get(&info->refcount);
786 spin_unlock_bh(&bat_priv->vis_hash_lock);
787
788 if (bat_priv->primary_if)
789 send_vis_packet(bat_priv, info);
790
791 spin_lock_bh(&bat_priv->vis_hash_lock);
792 send_list_del(info);
793 kref_put(&info->refcount, free_info);
794 }
795 spin_unlock_bh(&bat_priv->vis_hash_lock);
796 start_vis_timer(bat_priv);
797}
798
799/* init the vis server. this may only be called when if_list is already
800 * initialized (e.g. bat0 is initialized, interfaces have been added) */
801int vis_init(struct bat_priv *bat_priv)
802{
803 struct vis_packet *packet;
804 int hash_added;
805
806 if (bat_priv->vis_hash)
807 return 1;
808
809 spin_lock_bh(&bat_priv->vis_hash_lock);
810
811 bat_priv->vis_hash = hash_new(256);
812 if (!bat_priv->vis_hash) {
813 pr_err("Can't initialize vis_hash\n");
814 goto err;
815 }
816
817 bat_priv->my_vis_info = kmalloc(MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
818 if (!bat_priv->my_vis_info) {
819 pr_err("Can't initialize vis packet\n");
820 goto err;
821 }
822
823 bat_priv->my_vis_info->skb_packet = dev_alloc_skb(
824 sizeof(struct vis_packet) +
825 MAX_VIS_PACKET_SIZE +
826 sizeof(struct ethhdr));
827 if (!bat_priv->my_vis_info->skb_packet)
828 goto free_info;
829
830 skb_reserve(bat_priv->my_vis_info->skb_packet, sizeof(struct ethhdr));
831 packet = (struct vis_packet *)skb_put(
832 bat_priv->my_vis_info->skb_packet,
833 sizeof(struct vis_packet));
834
835 /* prefill the vis info */
836 bat_priv->my_vis_info->first_seen = jiffies -
837 msecs_to_jiffies(VIS_INTERVAL);
838 INIT_LIST_HEAD(&bat_priv->my_vis_info->recv_list);
839 INIT_LIST_HEAD(&bat_priv->my_vis_info->send_list);
840 kref_init(&bat_priv->my_vis_info->refcount);
841 bat_priv->my_vis_info->bat_priv = bat_priv;
842 packet->version = COMPAT_VERSION;
843 packet->packet_type = BAT_VIS;
844 packet->ttl = TTL;
845 packet->seqno = 0;
846 packet->entries = 0;
847
848 INIT_LIST_HEAD(&bat_priv->vis_send_list);
849
850 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
851 bat_priv->my_vis_info);
852 if (hash_added < 0) {
853 pr_err("Can't add own vis packet into hash\n");
854 /* not in hash, need to remove it manually. */
855 kref_put(&bat_priv->my_vis_info->refcount, free_info);
856 goto err;
857 }
858
859 spin_unlock_bh(&bat_priv->vis_hash_lock);
860 start_vis_timer(bat_priv);
861 return 1;
862
863free_info:
864 kfree(bat_priv->my_vis_info);
865 bat_priv->my_vis_info = NULL;
866err:
867 spin_unlock_bh(&bat_priv->vis_hash_lock);
868 vis_quit(bat_priv);
869 return 0;
870}
871
872/* Decrease the reference count on a hash item info */
873static void free_info_ref(void *data, void *arg)
874{
875 struct vis_info *info = data;
876
877 send_list_del(info);
878 kref_put(&info->refcount, free_info);
879}
880
881/* shutdown vis-server */
882void vis_quit(struct bat_priv *bat_priv)
883{
884 if (!bat_priv->vis_hash)
885 return;
886
887 cancel_delayed_work_sync(&bat_priv->vis_work);
888
889 spin_lock_bh(&bat_priv->vis_hash_lock);
890 /* properly remove, kill timers ... */
891 hash_delete(bat_priv->vis_hash, free_info_ref, NULL);
892 bat_priv->vis_hash = NULL;
893 bat_priv->my_vis_info = NULL;
894 spin_unlock_bh(&bat_priv->vis_hash_lock);
895}
896
897/* schedule packets for (re)transmission */
898static void start_vis_timer(struct bat_priv *bat_priv)
899{
900 INIT_DELAYED_WORK(&bat_priv->vis_work, send_vis_packets);
901 queue_delayed_work(bat_event_workqueue, &bat_priv->vis_work,
902 msecs_to_jiffies(VIS_INTERVAL));
903}
diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h
deleted file mode 100644
index 2c3b33089a9b..000000000000
--- a/drivers/staging/batman-adv/vis.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * Copyright (C) 2008-2010 B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich, Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_VIS_H_
23#define _NET_BATMAN_ADV_VIS_H_
24
25#define VIS_TIMEOUT 200 /* timeout of vis packets in seconds */
26
27int vis_seq_print_text(struct seq_file *seq, void *offset);
28void receive_server_sync_packet(struct bat_priv *bat_priv,
29 struct vis_packet *vis_packet,
30 int vis_info_len);
31void receive_client_update_packet(struct bat_priv *bat_priv,
32 struct vis_packet *vis_packet,
33 int vis_info_len);
34int vis_init(struct bat_priv *bat_priv);
35void vis_quit(struct bat_priv *bat_priv);
36
37#endif /* _NET_BATMAN_ADV_VIS_H_ */