diff options
author | Sven Eckelmann <sven@narfation.org> | 2010-12-16 17:28:17 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 18:20:05 -0500 |
commit | 63d5e5a727240b317b0c2fa2abeb32b367aea196 (patch) | |
tree | 2ad3bd8296e3cc8704112d8e03395572980e7f80 /drivers/staging | |
parent | 45241e50e3e741ee2a148693888b48e90e806de9 (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')
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 | ||
130 | source "drivers/staging/wlags49_h25/Kconfig" | 130 | source "drivers/staging/wlags49_h25/Kconfig" |
131 | 131 | ||
132 | source "drivers/staging/batman-adv/Kconfig" | ||
133 | |||
134 | source "drivers/staging/samsung-laptop/Kconfig" | 132 | source "drivers/staging/samsung-laptop/Kconfig" |
135 | 133 | ||
136 | source "drivers/staging/sm7xx/Kconfig" | 134 | source "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/ | |||
47 | obj-$(CONFIG_ZRAM) += zram/ | 47 | obj-$(CONFIG_ZRAM) += zram/ |
48 | obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ | 48 | obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ |
49 | obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ | 49 | obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ |
50 | obj-$(CONFIG_BATMAN_ADV) += batman-adv/ | ||
51 | obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/ | 50 | obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/ |
52 | obj-$(CONFIG_FB_SM7XX) += sm7xx/ | 51 | obj-$(CONFIG_FB_SM7XX) += sm7xx/ |
53 | obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ | 52 | obj-$(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 | |||
5 | config 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 | |||
17 | config 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 | |||
21 | obj-$(CONFIG_BATMAN_ADV) += batman-adv.o | ||
22 | batman-adv-y += aggregation.o | ||
23 | batman-adv-y += bat_debugfs.o | ||
24 | batman-adv-y += bat_sysfs.o | ||
25 | batman-adv-y += bitarray.o | ||
26 | batman-adv-y += gateway_client.o | ||
27 | batman-adv-y += gateway_common.o | ||
28 | batman-adv-y += hard-interface.o | ||
29 | batman-adv-y += hash.o | ||
30 | batman-adv-y += icmp_socket.o | ||
31 | batman-adv-y += main.o | ||
32 | batman-adv-y += originator.o | ||
33 | batman-adv-y += ring_buffer.o | ||
34 | batman-adv-y += routing.o | ||
35 | batman-adv-y += send.o | ||
36 | batman-adv-y += soft-interface.o | ||
37 | batman-adv-y += translation-table.o | ||
38 | batman-adv-y += unicast.o | ||
39 | batman-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 | |||
3 | BATMAN-ADV | ||
4 | ---------- | ||
5 | |||
6 | Batman advanced is a new approach to wireless networking which | ||
7 | does no longer operate on the IP basis. Unlike the batman daemon, | ||
8 | which exchanges information using UDP packets and sets routing | ||
9 | tables, batman-advanced operates on ISO/OSI Layer 2 only and uses | ||
10 | and routes (or better: bridges) Ethernet Frames. It emulates a | ||
11 | virtual network switch of all nodes participating. Therefore all | ||
12 | nodes appear to be link local, thus all higher operating proto- | ||
13 | cols won't be affected by any changes within the network. You can | ||
14 | run almost any protocol above batman advanced, prominent examples | ||
15 | are: IPv4, IPv6, DHCP, IPX. | ||
16 | |||
17 | Batman advanced was implemented as a Linux kernel driver to re- | ||
18 | duce the overhead to a minimum. It does not depend on any (other) | ||
19 | network driver, and can be used on wifi as well as ethernet lan, | ||
20 | vpn, etc ... (anything with ethernet-style layer 2). | ||
21 | |||
22 | CONFIGURATION | ||
23 | ------------- | ||
24 | |||
25 | Load the batman-adv module into your kernel: | ||
26 | |||
27 | # insmod batman-adv.ko | ||
28 | |||
29 | The module is now waiting for activation. You must add some in- | ||
30 | terfaces on which batman can operate. After loading the module | ||
31 | batman advanced will scan your systems interfaces to search for | ||
32 | compatible interfaces. Once found, it will create subfolders in | ||
33 | the /sys directories of each supported interface, e.g. | ||
34 | |||
35 | # ls /sys/class/net/eth0/batman_adv/ | ||
36 | # iface_status mesh_iface | ||
37 | |||
38 | If an interface does not have the "batman_adv" subfolder it prob- | ||
39 | ably is not supported. Not supported interfaces are: loopback, | ||
40 | non-ethernet and batman's own interfaces. | ||
41 | |||
42 | Note: After the module was loaded it will continuously watch for | ||
43 | new interfaces to verify the compatibility. There is no need to | ||
44 | reload the module if you plug your USB wifi adapter into your ma- | ||
45 | chine after batman advanced was initially loaded. | ||
46 | |||
47 | To 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 | |||
52 | Repeat this step for all interfaces you wish to add. Now batman | ||
53 | starts using/broadcasting on this/these interface(s). | ||
54 | |||
55 | By reading the "iface_status" file you can check its status: | ||
56 | |||
57 | # cat /sys/class/net/eth0/batman_adv/iface_status | ||
58 | # active | ||
59 | |||
60 | To 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 | |||
66 | All mesh wide settings can be found in batman's own interface | ||
67 | folder: | ||
68 | |||
69 | # ls /sys/class/net/bat0/mesh/ | ||
70 | # aggregated_ogms bonding fragmentation orig_interval | ||
71 | # vis_mode | ||
72 | |||
73 | |||
74 | There 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 | |||
81 | Some of the files contain all sort of status information regard- | ||
82 | ing the mesh network. For example, you can view the table of | ||
83 | originators (mesh participants) with: | ||
84 | |||
85 | # cat /sys/kernel/debug/batman_adv/bat0/originators | ||
86 | |||
87 | Other files allow to change batman's behaviour to better fit your | ||
88 | requirements. For instance, you can check the current originator | ||
89 | interval (value in milliseconds which determines how often batman | ||
90 | sends its broadcast packets): | ||
91 | |||
92 | # cat /sys/class/net/bat0/mesh/orig_interval | ||
93 | # 1000 | ||
94 | |||
95 | and also change its value: | ||
96 | |||
97 | # echo 3000 > /sys/class/net/bat0/mesh/orig_interval | ||
98 | |||
99 | In very mobile scenarios, you might want to adjust the originator | ||
100 | interval to a lower value. This will make the mesh more respon- | ||
101 | sive to topology changes, but will also increase the overhead. | ||
102 | |||
103 | |||
104 | USAGE | ||
105 | ----- | ||
106 | |||
107 | To make use of your newly created mesh, batman advanced provides | ||
108 | a new interface "bat0" which you should use from this point on. | ||
109 | All interfaces added to batman advanced are not relevant any | ||
110 | longer because batman handles them for you. Basically, one "hands | ||
111 | over" the data by using the batman interface and batman will make | ||
112 | sure it reaches its destination. | ||
113 | |||
114 | The "bat0" interface can be used like any other regular inter- | ||
115 | face. It needs an IP address which can be either statically con- | ||
116 | figured 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 | |||
122 | Note: In order to avoid problems remove all IP addresses previ- | ||
123 | ously assigned to interfaces now used by batman advanced, e.g. | ||
124 | |||
125 | # ifconfig eth0 0.0.0.0 | ||
126 | |||
127 | |||
128 | VISUALIZATION | ||
129 | ------------- | ||
130 | |||
131 | If you want topology visualization, at least one mesh node must | ||
132 | be configured as VIS-server: | ||
133 | |||
134 | # echo "server" > /sys/class/net/bat0/mesh/vis_mode | ||
135 | |||
136 | Each node is either configured as "server" or as "client" (de- | ||
137 | fault: "client"). Clients send their topology data to the server | ||
138 | next to them, and server synchronize with other servers. If there | ||
139 | is no server configured (default) within the mesh, no topology | ||
140 | information will be transmitted. With these "synchronizing | ||
141 | servers", there can be 1 or more vis servers sharing the same (or | ||
142 | at least very similar) data. | ||
143 | |||
144 | When configured as server, you can get a topology snapshot of | ||
145 | your mesh: | ||
146 | |||
147 | # cat /sys/kernel/debug/batman_adv/bat0/vis_data | ||
148 | |||
149 | This raw output is intended to be easily parsable and convertable | ||
150 | with other tools. Have a look at the batctl README if you want a | ||
151 | vis output in dot or json format for instance and how those out- | ||
152 | puts could then be visualised in an image. | ||
153 | |||
154 | The raw format consists of comma separated values per entry where | ||
155 | each entry is giving information about a certain source inter- | ||
156 | face. 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 | |||
167 | The TQ value has a range from 4 to 255 with 255 being the best. | ||
168 | The HNA entries are showing which hosts are connected to the mesh | ||
169 | via bat0 or being bridged into the mesh network. The PRIMARY/SEC | ||
170 | values are only applied on primary interfaces | ||
171 | |||
172 | |||
173 | LOGGING/DEBUGGING | ||
174 | ----------------- | ||
175 | |||
176 | All error messages, warnings and information messages are sent to | ||
177 | the kernel log. Depending on your operating system distribution | ||
178 | this can be read in one of a number of ways. Try using the com- | ||
179 | mands: dmesg, logread, or looking in the files /var/log/kern.log | ||
180 | or /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 | |||
185 | When investigating problems with your mesh network it is some- | ||
186 | times necessary to see more detail debug messages. This must be | ||
187 | enabled when compiling the batman-adv module. When building bat- | ||
188 | man-adv as part of kernel, use "make menuconfig" and enable the | ||
189 | option "B.A.T.M.A.N. debugging". | ||
190 | |||
191 | Those additional debug messages can be accessed using a special | ||
192 | file in debugfs | ||
193 | |||
194 | # cat /sys/kernel/debug/batman_adv/bat0/log | ||
195 | |||
196 | The additional debug output is by default disabled. It can be en- | ||
197 | abled during run time. Following log_levels are defined: | ||
198 | |||
199 | 0 - All debug output disabled | ||
200 | 1 - Enable messages related to routing / flooding / broadcasting | ||
201 | 2 - Enable route or hna added / changed / deleted | ||
202 | 3 - Enable all messages | ||
203 | |||
204 | The 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 | |||
209 | will enable debug messages for when routes or HNAs change. | ||
210 | |||
211 | |||
212 | BATCTL | ||
213 | ------ | ||
214 | |||
215 | As batman advanced operates on layer 2 all hosts participating in | ||
216 | the virtual switch are completely transparent for all protocols | ||
217 | above layer 2. Therefore the common diagnosis tools do not work | ||
218 | as expected. To overcome these problems batctl was created. At | ||
219 | the moment the batctl contains ping, traceroute, tcpdump and | ||
220 | interfaces to the kernel module settings. | ||
221 | |||
222 | For more information, please see the manpage (man batctl). | ||
223 | |||
224 | batctl is available on http://www.open-mesh.org/ | ||
225 | |||
226 | |||
227 | CONTACT | ||
228 | ------- | ||
229 | |||
230 | Please send us comments, experiences, questions, anything :) | ||
231 | |||
232 | IRC: #batman on irc.freenode.org | ||
233 | Mailing-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 | |||
237 | You can also contact the Authors: | ||
238 | |||
239 | Marek Lindner <lindner_marek@yahoo.de> | ||
240 | Simon 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 | |||
5 | Please 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 */ | ||
28 | static 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 */ | ||
34 | static 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 */ | ||
100 | static 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 */ | ||
171 | static 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 | |||
189 | void 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 */ | ||
249 | void 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? */ | ||
28 | static 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 | |||
36 | void 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); | ||
40 | void 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 | |||
36 | static 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 | |||
42 | static int log_buff_len = LOG_BUF_LEN; | ||
43 | |||
44 | static 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 | |||
53 | static 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 | |||
79 | int 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 | |||
93 | static 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 | |||
101 | static int log_release(struct inode *inode, struct file *file) | ||
102 | { | ||
103 | dec_module_count(); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static 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 | |||
161 | static 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 | |||
174 | static 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 | |||
182 | static 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 | |||
203 | err: | ||
204 | return 1; | ||
205 | } | ||
206 | |||
207 | static 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 */ | ||
213 | static int debug_log_setup(struct bat_priv *bat_priv) | ||
214 | { | ||
215 | bat_priv->debug_log = NULL; | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static void debug_log_cleanup(struct bat_priv *bat_priv) | ||
220 | { | ||
221 | return; | ||
222 | } | ||
223 | #endif | ||
224 | |||
225 | static 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 | |||
231 | static 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 | |||
237 | static 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 | |||
243 | static 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 | |||
249 | static 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 | |||
255 | static 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 | |||
261 | struct bat_debuginfo { | ||
262 | struct attribute attr; | ||
263 | const struct file_operations fops; | ||
264 | }; | ||
265 | |||
266 | #define BAT_DEBUGINFO(_name, _mode, _open) \ | ||
267 | struct 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 | |||
278 | static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); | ||
279 | static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); | ||
280 | static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open); | ||
281 | static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); | ||
282 | static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); | ||
283 | static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open); | ||
284 | |||
285 | static 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 | |||
295 | void 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 | |||
302 | void debugfs_destroy(void) | ||
303 | { | ||
304 | if (bat_debugfs) { | ||
305 | debugfs_remove_recursive(bat_debugfs); | ||
306 | bat_debugfs = NULL; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | int 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; | ||
339 | rem_attr: | ||
340 | debugfs_remove_recursive(bat_priv->debug_dir); | ||
341 | bat_priv->debug_dir = NULL; | ||
342 | out: | ||
343 | #ifdef CONFIG_DEBUG_FS | ||
344 | return -ENOMEM; | ||
345 | #else | ||
346 | return 0; | ||
347 | #endif /* CONFIG_DEBUG_FS */ | ||
348 | } | ||
349 | |||
350 | void 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 | |||
28 | void debugfs_init(void); | ||
29 | void debugfs_destroy(void); | ||
30 | int debugfs_add_meshif(struct net_device *dev); | ||
31 | void 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) \ | ||
37 | struct 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) \ | ||
45 | ssize_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) \ | ||
55 | ssize_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) \ | ||
72 | ssize_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) \ | ||
82 | ssize_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 | |||
97 | static 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 | |||
134 | static 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 | |||
149 | static 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 | |||
186 | static 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 | |||
202 | static 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 | |||
213 | static 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 | |||
254 | static 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 | |||
260 | static 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 | |||
281 | static 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 | |||
333 | static 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 | |||
348 | static 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 | |||
359 | BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); | ||
360 | BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | ||
361 | BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); | ||
362 | static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); | ||
363 | static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); | ||
364 | BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); | ||
365 | BAT_ATTR_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL); | ||
366 | BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE, | ||
367 | post_gw_deselect); | ||
368 | static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth, | ||
369 | store_gw_bwidth); | ||
370 | #ifdef CONFIG_BATMAN_ADV_DEBUG | ||
371 | BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL); | ||
372 | #endif | ||
373 | |||
374 | static 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 | |||
390 | int 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 | |||
418 | rem_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; | ||
424 | out: | ||
425 | return -ENOMEM; | ||
426 | } | ||
427 | |||
428 | void 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 | |||
440 | static 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 | |||
458 | static 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 | |||
511 | static 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 | |||
545 | static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR, | ||
546 | show_mesh_iface, store_mesh_iface); | ||
547 | static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL); | ||
548 | |||
549 | static struct bat_attribute *batman_attrs[] = { | ||
550 | &bat_attr_mesh_iface, | ||
551 | &bat_attr_iface_status, | ||
552 | NULL, | ||
553 | }; | ||
554 | |||
555 | int 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 | |||
582 | rem_attr: | ||
583 | for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) | ||
584 | sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr)); | ||
585 | out: | ||
586 | return -ENOMEM; | ||
587 | } | ||
588 | |||
589 | void 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 | |||
29 | struct 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 | |||
37 | int sysfs_add_meshif(struct net_device *dev); | ||
38 | void sysfs_del_meshif(struct net_device *dev); | ||
39 | int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev); | ||
40 | void 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 */ | ||
29 | uint8_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 */ | ||
51 | void 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. */ | ||
68 | static 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 | |||
116 | static 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 | */ | ||
130 | char 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 | */ | ||
193 | int 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 */ | ||
32 | uint8_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 */ | ||
36 | void 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 */ | ||
41 | char 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? */ | ||
45 | int 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 | |||
31 | static 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 | |||
39 | static 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 | |||
47 | void *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 | |||
57 | void 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 | |||
67 | static 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 | |||
79 | void 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 | |||
187 | void 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 | |||
228 | deselect: | ||
229 | gw_deselect(bat_priv); | ||
230 | } | ||
231 | |||
232 | static 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 | |||
261 | void 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 | |||
304 | void 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 | |||
309 | void 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 | |||
335 | static 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 | |||
355 | int 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 | |||
403 | int 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 | |||
25 | void gw_deselect(struct bat_priv *bat_priv); | ||
26 | void gw_election(struct bat_priv *bat_priv); | ||
27 | void *gw_get_selected(struct bat_priv *bat_priv); | ||
28 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); | ||
29 | void gw_node_update(struct bat_priv *bat_priv, | ||
30 | struct orig_node *orig_node, uint8_t new_gwflags); | ||
31 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); | ||
32 | void gw_node_purge(struct bat_priv *bat_priv); | ||
33 | int gw_client_seq_print_text(struct seq_file *seq, void *offset); | ||
34 | int 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 */ | ||
27 | static 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 */ | ||
62 | void 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 | |||
78 | static 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 | |||
138 | ssize_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 | |||
175 | end: | ||
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 | |||
25 | enum 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 | |||
35 | void gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up); | ||
36 | ssize_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 */ | ||
35 | static DEFINE_SPINLOCK(if_list_lock); | ||
36 | |||
37 | static 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 | |||
46 | struct 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 | |||
58 | out: | ||
59 | if (batman_if) | ||
60 | kref_get(&batman_if->refcount); | ||
61 | |||
62 | rcu_read_unlock(); | ||
63 | return batman_if; | ||
64 | } | ||
65 | |||
66 | static 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 | |||
93 | static 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 | |||
108 | out: | ||
109 | if (batman_if) | ||
110 | kref_get(&batman_if->refcount); | ||
111 | |||
112 | rcu_read_unlock(); | ||
113 | return batman_if; | ||
114 | } | ||
115 | |||
116 | static 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 | |||
128 | static 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 | |||
159 | static 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 | |||
167 | static 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 | |||
175 | static 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 | |||
201 | int 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(); | ||
225 | out: | ||
226 | return min_mtu; | ||
227 | } | ||
228 | |||
229 | /* adjusts the MTU if a new interface with a smaller MTU appeared. */ | ||
230 | void 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 | |||
239 | static 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 | |||
265 | static 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 | |||
279 | int 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 | |||
364 | out: | ||
365 | return 0; | ||
366 | |||
367 | err: | ||
368 | return -ENOMEM; | ||
369 | } | ||
370 | |||
371 | void 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 | |||
415 | static 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 | |||
454 | free_if: | ||
455 | kfree(batman_if); | ||
456 | release_dev: | ||
457 | dev_put(net_dev); | ||
458 | out: | ||
459 | return NULL; | ||
460 | } | ||
461 | |||
462 | static 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 | |||
477 | void 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 | |||
498 | static 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 | |||
545 | hardif_put: | ||
546 | kref_put(&batman_if->refcount, hardif_free_ref); | ||
547 | out: | ||
548 | return NOTIFY_DONE; | ||
549 | } | ||
550 | |||
551 | /* receive a packet with the batman ethertype coming on a hard | ||
552 | * interface */ | ||
553 | int 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 | |||
644 | err_free: | ||
645 | kfree_skb(skb); | ||
646 | err_out: | ||
647 | return NET_RX_DROP; | ||
648 | } | ||
649 | |||
650 | struct 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 | |||
32 | extern struct notifier_block hard_if_notifier; | ||
33 | |||
34 | struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev); | ||
35 | int hardif_enable_interface(struct batman_if *batman_if, char *iface_name); | ||
36 | void hardif_disable_interface(struct batman_if *batman_if); | ||
37 | void hardif_remove_interfaces(void); | ||
38 | int batman_skb_recv(struct sk_buff *skb, | ||
39 | struct net_device *dev, | ||
40 | struct packet_type *ptype, | ||
41 | struct net_device *orig_dev); | ||
42 | int hardif_min_mtu(struct net_device *soft_iface); | ||
43 | void update_min_mtu(struct net_device *soft_iface); | ||
44 | |||
45 | static 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 */ | ||
26 | static 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. */ | ||
37 | void hash_destroy(struct hashtable_t *hash) | ||
38 | { | ||
39 | kfree(hash->table); | ||
40 | kfree(hash); | ||
41 | } | ||
42 | |||
43 | /* allocates and clears the hash */ | ||
44 | struct 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. */ | ||
70 | void *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 */ | ||
35 | typedef 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 */ | ||
40 | typedef int (*hashdata_choose_cb)(void *, int); | ||
41 | typedef void (*hashdata_free_cb)(void *, void *); | ||
42 | |||
43 | struct element_t { | ||
44 | void *data; /* pointer to the data */ | ||
45 | struct hlist_node hlist; /* bucket list pointer */ | ||
46 | }; | ||
47 | |||
48 | struct hash_it_t { | ||
49 | size_t index; | ||
50 | struct hlist_node *walk; | ||
51 | struct hlist_node *safe; | ||
52 | }; | ||
53 | |||
54 | struct 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 */ | ||
61 | struct 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. */ | ||
67 | void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t); | ||
68 | |||
69 | /* free only the hashtable and the hash itself. */ | ||
70 | void 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. */ | ||
75 | static 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 */ | ||
100 | static 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. */ | ||
138 | static 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 */ | ||
160 | static 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 */ | ||
186 | static 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. */ | ||
226 | static 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 | |||
33 | static struct socket_client *socket_client_hash[256]; | ||
34 | |||
35 | static void bat_socket_add_packet(struct socket_client *socket_client, | ||
36 | struct icmp_packet_rr *icmp_packet, | ||
37 | size_t icmp_len); | ||
38 | |||
39 | void bat_socket_init(void) | ||
40 | { | ||
41 | memset(socket_client_hash, 0, sizeof(socket_client_hash)); | ||
42 | } | ||
43 | |||
44 | static 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 | |||
83 | static 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 | |||
109 | static 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 | |||
153 | static 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 | |||
257 | unlock: | ||
258 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
259 | dst_unreach: | ||
260 | icmp_packet->msg_type = DESTINATION_UNREACHABLE; | ||
261 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); | ||
262 | free_skb: | ||
263 | kfree_skb(skb); | ||
264 | out: | ||
265 | return len; | ||
266 | } | ||
267 | |||
268 | static 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 | |||
280 | static 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 | |||
290 | int 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 | |||
304 | err: | ||
305 | return 1; | ||
306 | } | ||
307 | |||
308 | static 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 | |||
350 | void 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 | |||
29 | void bat_socket_init(void); | ||
30 | int bat_socket_setup(struct bat_priv *bat_priv); | ||
31 | void 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 | |||
37 | struct list_head if_list; | ||
38 | |||
39 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
40 | |||
41 | struct workqueue_struct *bat_event_workqueue; | ||
42 | |||
43 | static 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 | |||
66 | static 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 | |||
79 | int 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 | |||
115 | err: | ||
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 | |||
121 | end: | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | void 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 | |||
146 | void inc_module_count(void) | ||
147 | { | ||
148 | try_module_get(THIS_MODULE); | ||
149 | } | ||
150 | |||
151 | void dec_module_count(void) | ||
152 | { | ||
153 | module_put(THIS_MODULE); | ||
154 | } | ||
155 | |||
156 | int 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 | |||
175 | module_init(batman_init); | ||
176 | module_exit(batman_exit); | ||
177 | |||
178 | MODULE_LICENSE("GPL"); | ||
179 | |||
180 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
181 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
182 | MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE); | ||
183 | #ifdef REVISION_VERSION | ||
184 | MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION); | ||
185 | #else | ||
186 | MODULE_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 | |||
130 | extern struct list_head if_list; | ||
131 | |||
132 | extern unsigned char broadcast_addr[]; | ||
133 | extern struct workqueue_struct *bat_event_workqueue; | ||
134 | |||
135 | int mesh_init(struct net_device *soft_iface); | ||
136 | void mesh_free(struct net_device *soft_iface); | ||
137 | void inc_module_count(void); | ||
138 | void dec_module_count(void); | ||
139 | int is_my_mac(uint8_t *addr); | ||
140 | |||
141 | #ifdef CONFIG_BATMAN_ADV_DEBUG | ||
142 | int 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 */ | ||
151 | static 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 | |||
34 | static void purge_orig(struct work_struct *work); | ||
35 | |||
36 | static 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 | |||
42 | int 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 | |||
57 | err: | ||
58 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | struct neigh_node * | ||
63 | create_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 | |||
86 | static 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 | |||
109 | void 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 */ | ||
124 | struct 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; | ||
187 | free_bcast_own_sum: | ||
188 | kfree(orig_node->bcast_own_sum); | ||
189 | free_bcast_own: | ||
190 | kfree(orig_node->bcast_own); | ||
191 | free_orig_node: | ||
192 | kfree(orig_node); | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | static 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 | |||
241 | static 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 | |||
269 | static 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 | |||
302 | static 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 | |||
313 | void purge_orig_ref(struct bat_priv *bat_priv) | ||
314 | { | ||
315 | _purge_orig(bat_priv); | ||
316 | } | ||
317 | |||
318 | int 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 | |||
389 | static 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 | |||
419 | int 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 | |||
441 | err: | ||
442 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
443 | return -ENOMEM; | ||
444 | } | ||
445 | |||
446 | static 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 | |||
471 | free_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 | |||
491 | free_own_sum: | ||
492 | kfree(orig_node->bcast_own_sum); | ||
493 | orig_node->bcast_own_sum = data_ptr; | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | int 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 | |||
543 | err: | ||
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 | |||
25 | int originator_init(struct bat_priv *bat_priv); | ||
26 | void originator_free(struct bat_priv *bat_priv); | ||
27 | void purge_orig_ref(struct bat_priv *bat_priv); | ||
28 | struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr); | ||
29 | struct neigh_node * | ||
30 | create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, | ||
31 | uint8_t *neigh, struct batman_if *if_incoming); | ||
32 | int orig_seq_print_text(struct seq_file *seq, void *offset); | ||
33 | int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); | ||
34 | int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); | ||
35 | |||
36 | |||
37 | /* returns 1 if they are the same originator */ | ||
38 | static 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 */ | ||
45 | static 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 | |||
54 | struct 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 | |||
70 | struct 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 */ | ||
85 | struct 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 | |||
98 | struct 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 | |||
105 | struct 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 | |||
115 | struct 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 | |||
123 | struct 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 | |||
25 | void 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 | |||
31 | uint8_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 | |||
25 | void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value); | ||
26 | uint8_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 | |||
39 | void 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 | |||
62 | static 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 | |||
80 | static 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 | |||
115 | void 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 | |||
131 | static 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 | |||
240 | static 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 | |||
323 | update_hna: | ||
324 | update_routes(bat_priv, orig_node, orig_node->router, | ||
325 | hna_buff, tmp_hna_buff_len); | ||
326 | |||
327 | update_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 | */ | ||
345 | static 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 | */ | ||
373 | static 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 */ | ||
428 | static 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 */ | ||
442 | void 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 | |||
534 | void 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 | |||
761 | int 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 | |||
801 | static 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 | |||
862 | static 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 | |||
925 | int 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. */ | ||
1017 | struct 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 | |||
1110 | static 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 | |||
1135 | int 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 | |||
1216 | int 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 | |||
1235 | int 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 | |||
1269 | int 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 | |||
1347 | int 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 | |||
27 | void slide_own_bcast_window(struct batman_if *batman_if); | ||
28 | void 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); | ||
32 | void 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); | ||
35 | int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, | ||
36 | int hdr_size); | ||
37 | int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
38 | int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
39 | int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
40 | int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
41 | int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
42 | int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
43 | struct neigh_node *find_router(struct bat_priv *bat_priv, | ||
44 | struct orig_node *orig_node, struct batman_if *recv_if); | ||
45 | void 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 | |||
35 | static void send_outstanding_bcast_packet(struct work_struct *work); | ||
36 | |||
37 | /* apply hop penalty for a normal link */ | ||
38 | static 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 */ | ||
45 | static 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 */ | ||
53 | static 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 */ | ||
60 | int 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); | ||
100 | send_skb_err: | ||
101 | kfree_skb(skb); | ||
102 | return NET_XMIT_DROP; | ||
103 | } | ||
104 | |||
105 | /* Send a packet to a given interface */ | ||
106 | static 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 */ | ||
163 | static 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 | |||
218 | static 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 | |||
245 | void 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 | |||
305 | void 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 | |||
367 | static 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 | |||
374 | static 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. */ | ||
401 | int 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 | |||
438 | packet_free: | ||
439 | kfree(forw_packet); | ||
440 | out_and_inc: | ||
441 | atomic_inc(&bat_priv->bcast_queue_left); | ||
442 | out: | ||
443 | return NETDEV_TX_BUSY; | ||
444 | } | ||
445 | |||
446 | static 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 | |||
486 | out: | ||
487 | forw_packet_free(forw_packet); | ||
488 | atomic_inc(&bat_priv->bcast_queue_left); | ||
489 | } | ||
490 | |||
491 | void 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 | |||
517 | out: | ||
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 | |||
525 | void 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 | |||
27 | int send_skb_packet(struct sk_buff *skb, | ||
28 | struct batman_if *batman_if, | ||
29 | uint8_t *dst_addr); | ||
30 | void schedule_own_packet(struct batman_if *batman_if); | ||
31 | void 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); | ||
36 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); | ||
37 | void send_outstanding_bat_packet(struct work_struct *work); | ||
38 | void 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 | |||
43 | static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); | ||
44 | static void bat_get_drvinfo(struct net_device *dev, | ||
45 | struct ethtool_drvinfo *info); | ||
46 | static u32 bat_get_msglevel(struct net_device *dev); | ||
47 | static void bat_set_msglevel(struct net_device *dev, u32 value); | ||
48 | static u32 bat_get_link(struct net_device *dev); | ||
49 | static u32 bat_get_rx_csum(struct net_device *dev); | ||
50 | static int bat_set_rx_csum(struct net_device *dev, u32 data); | ||
51 | |||
52 | static 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 | |||
62 | int 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 | |||
82 | static 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 | |||
90 | static 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 | |||
98 | void 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 | |||
132 | static 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 | |||
165 | found: | ||
166 | kref_get(&softif_neigh->refcount); | ||
167 | out: | ||
168 | rcu_read_unlock(); | ||
169 | return softif_neigh; | ||
170 | } | ||
171 | |||
172 | int 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 | |||
219 | static 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 | |||
287 | out: | ||
288 | kref_put(&softif_neigh->refcount, softif_neigh_free_ref); | ||
289 | err: | ||
290 | kfree_skb(skb); | ||
291 | return; | ||
292 | } | ||
293 | |||
294 | static int interface_open(struct net_device *dev) | ||
295 | { | ||
296 | netif_start_queue(dev); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int interface_release(struct net_device *dev) | ||
301 | { | ||
302 | netif_stop_queue(dev); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static 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 | |||
312 | static 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 | |||
331 | static 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 | |||
342 | int 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 | |||
432 | dropped: | ||
433 | kfree_skb(skb); | ||
434 | dropped_freed: | ||
435 | bat_priv->stats.tx_dropped++; | ||
436 | end: | ||
437 | return NETDEV_TX_OK; | ||
438 | } | ||
439 | |||
440 | void 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 | |||
515 | dropped: | ||
516 | kfree_skb(skb); | ||
517 | out: | ||
518 | return; | ||
519 | } | ||
520 | |||
521 | #ifdef HAVE_NET_DEVICE_OPS | ||
522 | static 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 | |||
533 | static 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 | |||
569 | struct 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 | |||
627 | unreg_debugfs: | ||
628 | debugfs_del_meshif(soft_iface); | ||
629 | unreg_sysfs: | ||
630 | sysfs_del_meshif(soft_iface); | ||
631 | unreg_soft_iface: | ||
632 | unregister_netdev(soft_iface); | ||
633 | return NULL; | ||
634 | |||
635 | free_soft_iface: | ||
636 | free_netdev(soft_iface); | ||
637 | out: | ||
638 | return NULL; | ||
639 | } | ||
640 | |||
641 | void 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 */ | ||
650 | static 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 | |||
666 | static 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 | |||
675 | static u32 bat_get_msglevel(struct net_device *dev) | ||
676 | { | ||
677 | return -EOPNOTSUPP; | ||
678 | } | ||
679 | |||
680 | static void bat_set_msglevel(struct net_device *dev, u32 value) | ||
681 | { | ||
682 | } | ||
683 | |||
684 | static u32 bat_get_link(struct net_device *dev) | ||
685 | { | ||
686 | return 1; | ||
687 | } | ||
688 | |||
689 | static u32 bat_get_rx_csum(struct net_device *dev) | ||
690 | { | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static 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 | |||
25 | int my_skb_head_push(struct sk_buff *skb, unsigned int len); | ||
26 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset); | ||
27 | void softif_neigh_purge(struct bat_priv *bat_priv); | ||
28 | int interface_tx(struct sk_buff *skb, struct net_device *soft_iface); | ||
29 | void interface_rx(struct net_device *soft_iface, | ||
30 | struct sk_buff *skb, struct batman_if *recv_if, | ||
31 | int hdr_size); | ||
32 | struct net_device *softif_create(char *name); | ||
33 | void 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 | |||
2 | What: /sys/class/net/<iface>/batman-adv/mesh_iface | ||
3 | Date: May 2010 | ||
4 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
5 | Description: | ||
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 | |||
10 | What: /sys/class/net/<iface>/batman-adv/iface_status | ||
11 | Date: May 2010 | ||
12 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
13 | Description: | ||
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 | |||
2 | What: /sys/class/net/<mesh_iface>/mesh/aggregated_ogms | ||
3 | Date: May 2010 | ||
4 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
5 | Description: | ||
6 | Indicates whether the batman protocol messages of the | ||
7 | mesh <mesh_iface> shall be aggregated or not. | ||
8 | |||
9 | What: /sys/class/net/<mesh_iface>/mesh/bonding | ||
10 | Date: June 2010 | ||
11 | Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> | ||
12 | Description: | ||
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 | |||
17 | What: /sys/class/net/<mesh_iface>/mesh/fragmentation | ||
18 | Date: October 2010 | ||
19 | Contact: Andreas Langer <an.langer@gmx.de> | ||
20 | Description: | ||
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 | |||
25 | What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth | ||
26 | Date: October 2010 | ||
27 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
28 | Description: | ||
29 | Defines the bandwidth which is propagated by this | ||
30 | node if gw_mode was set to 'server'. | ||
31 | |||
32 | What: /sys/class/net/<mesh_iface>/mesh/gw_mode | ||
33 | Date: October 2010 | ||
34 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
35 | Description: | ||
36 | Defines the state of the gateway features. Can be | ||
37 | either 'off', 'client' or 'server'. | ||
38 | |||
39 | What: /sys/class/net/<mesh_iface>/mesh/gw_sel_class | ||
40 | Date: October 2010 | ||
41 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
42 | Description: | ||
43 | Defines the selection criteria this node will use | ||
44 | to choose a gateway if gw_mode was set to 'client'. | ||
45 | |||
46 | What: /sys/class/net/<mesh_iface>/mesh/orig_interval | ||
47 | Date: May 2010 | ||
48 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
49 | Description: | ||
50 | Defines the interval in milliseconds in which batman | ||
51 | sends its protocol messages. | ||
52 | |||
53 | What: /sys/class/net/<mesh_iface>/mesh/hop_penalty | ||
54 | Date: Oct 2010 | ||
55 | Contact: Linus Lüssing <linus.luessing@web.de> | ||
56 | Description: | ||
57 | Defines the penalty which will be applied to an | ||
58 | originator message's tq-field on every hop. | ||
59 | |||
60 | What: /sys/class/net/<mesh_iface>/mesh/vis_mode | ||
61 | Date: May 2010 | ||
62 | Contact: Marek Lindner <lindner_marek@yahoo.de> | ||
63 | Description: | ||
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 | |||
29 | static void hna_local_purge(struct work_struct *work); | ||
30 | static void _hna_global_del_orig(struct bat_priv *bat_priv, | ||
31 | struct hna_global_entry *hna_global_entry, | ||
32 | char *message); | ||
33 | |||
34 | static 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 | |||
40 | int 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 | |||
56 | void 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 | |||
143 | int 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 | |||
173 | int 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 | |||
224 | static 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 | |||
233 | static 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 | |||
245 | void 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 | |||
261 | static 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 | |||
290 | void 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 | |||
300 | int 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 | |||
313 | void 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 | |||
402 | int 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 | |||
453 | static 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 | |||
467 | void 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 | |||
500 | static void hna_global_del(void *data, void *arg) | ||
501 | { | ||
502 | kfree(data); | ||
503 | } | ||
504 | |||
505 | void 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 | |||
514 | struct 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 | |||
27 | int hna_local_init(struct bat_priv *bat_priv); | ||
28 | void hna_local_add(struct net_device *soft_iface, uint8_t *addr); | ||
29 | void hna_local_remove(struct bat_priv *bat_priv, | ||
30 | uint8_t *addr, char *message); | ||
31 | int hna_local_fill_buffer(struct bat_priv *bat_priv, | ||
32 | unsigned char *buff, int buff_len); | ||
33 | int hna_local_seq_print_text(struct seq_file *seq, void *offset); | ||
34 | void hna_local_free(struct bat_priv *bat_priv); | ||
35 | int hna_global_init(struct bat_priv *bat_priv); | ||
36 | void hna_global_add_orig(struct bat_priv *bat_priv, | ||
37 | struct orig_node *orig_node, | ||
38 | unsigned char *hna_buff, int hna_buff_len); | ||
39 | int hna_global_seq_print_text(struct seq_file *seq, void *offset); | ||
40 | void hna_global_del_orig(struct bat_priv *bat_priv, | ||
41 | struct orig_node *orig_node, char *message); | ||
42 | void hna_global_free(struct bat_priv *bat_priv); | ||
43 | struct 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 | |||
36 | struct 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 | */ | ||
67 | struct 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 | |||
95 | struct 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 | */ | ||
107 | struct 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 | |||
123 | struct 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 | |||
172 | struct 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 | |||
181 | struct socket_packet { | ||
182 | struct list_head list; | ||
183 | size_t icmp_len; | ||
184 | struct icmp_packet_rr icmp_packet; | ||
185 | }; | ||
186 | |||
187 | struct hna_local_entry { | ||
188 | uint8_t addr[ETH_ALEN]; | ||
189 | unsigned long last_seen; | ||
190 | char never_purge; | ||
191 | }; | ||
192 | |||
193 | struct 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 | */ | ||
202 | struct 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 | */ | ||
218 | struct if_list_entry { | ||
219 | uint8_t addr[ETH_ALEN]; | ||
220 | bool primary; | ||
221 | struct hlist_node list; | ||
222 | }; | ||
223 | |||
224 | struct 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 | |||
232 | struct frag_packet_list_entry { | ||
233 | struct list_head list; | ||
234 | uint16_t seqno; | ||
235 | struct sk_buff *skb; | ||
236 | }; | ||
237 | |||
238 | struct 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 | |||
251 | struct 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 | |||
257 | struct recvlist_node { | ||
258 | struct list_head list; | ||
259 | uint8_t mac[ETH_ALEN]; | ||
260 | }; | ||
261 | |||
262 | struct 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 | |||
34 | static 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 | |||
75 | static 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 | |||
91 | static 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 | |||
112 | static 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 | |||
145 | mov_tail: | ||
146 | list_move_tail(&tfp->list, head); | ||
147 | return NULL; | ||
148 | } | ||
149 | |||
150 | void 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 | */ | ||
171 | int 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; | ||
213 | out: | ||
214 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | int 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 | |||
266 | drop_frag: | ||
267 | kfree_skb(frag_skb); | ||
268 | dropped: | ||
269 | kfree_skb(skb); | ||
270 | return NET_RX_DROP; | ||
271 | } | ||
272 | |||
273 | int 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 | |||
338 | unlock: | ||
339 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
340 | dropped: | ||
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 | |||
28 | int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | ||
29 | struct sk_buff **new_skb); | ||
30 | void frag_list_free(struct list_head *head); | ||
31 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv); | ||
32 | int 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 | |||
49 | static void start_vis_timer(struct bat_priv *bat_priv); | ||
50 | |||
51 | /* free the info */ | ||
52 | static 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 */ | ||
70 | static 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 */ | ||
83 | static 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 */ | ||
108 | static 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 | |||
129 | static 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 | |||
145 | static 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 */ | ||
162 | static 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 | |||
175 | int 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. */ | ||
289 | static 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. */ | ||
299 | static 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. */ | ||
308 | static 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 */ | ||
324 | static 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. */ | ||
343 | static 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. */ | ||
439 | void 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); | ||
459 | end: | ||
460 | spin_unlock_bh(&bat_priv->vis_hash_lock); | ||
461 | } | ||
462 | |||
463 | /* handle an incoming client update packet and schedule forward if needed. */ | ||
464 | void 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 | |||
503 | end: | ||
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 */ | ||
511 | static 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. */ | ||
536 | static 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 */ | ||
549 | static 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 */ | ||
639 | static 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 | |||
662 | static 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 | |||
709 | static 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 | |||
739 | out: | ||
740 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
741 | } | ||
742 | |||
743 | /* only send one vis packet. called from send_vis_packets() */ | ||
744 | static 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. */ | ||
766 | static 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) */ | ||
801 | int 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 | |||
863 | free_info: | ||
864 | kfree(bat_priv->my_vis_info); | ||
865 | bat_priv->my_vis_info = NULL; | ||
866 | err: | ||
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 */ | ||
873 | static 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 */ | ||
882 | void 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 */ | ||
898 | static 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 | |||
27 | int vis_seq_print_text(struct seq_file *seq, void *offset); | ||
28 | void receive_server_sync_packet(struct bat_priv *bat_priv, | ||
29 | struct vis_packet *vis_packet, | ||
30 | int vis_info_len); | ||
31 | void receive_client_update_packet(struct bat_priv *bat_priv, | ||
32 | struct vis_packet *vis_packet, | ||
33 | int vis_info_len); | ||
34 | int vis_init(struct bat_priv *bat_priv); | ||
35 | void vis_quit(struct bat_priv *bat_priv); | ||
36 | |||
37 | #endif /* _NET_BATMAN_ADV_VIS_H_ */ | ||