diff options
46 files changed, 0 insertions, 10314 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index f2d9fe8cde5..923e28f8320 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 10c72bb1940..4e6797f6444 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 8553f351745..00000000000 --- 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 d936aeccd19..00000000000 --- 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 77f0cdd5b0d..00000000000 --- 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 ba69ba3ab62..00000000000 --- 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 0c92e3b35ab..00000000000 --- 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 71a91b3da91..00000000000 --- 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 0ae81d07f10..00000000000 --- 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 72df532b7d5..00000000000 --- 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 cd7bb51825f..00000000000 --- 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 7f186c007b4..00000000000 --- 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 814274fbaa2..00000000000 --- 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 77b1e61847e..00000000000 --- 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 0065ffb8d96..00000000000 --- 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 4585e654984..00000000000 --- 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 b962982f017..00000000000 --- 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 5e728d0b795..00000000000 --- 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 c3c7b7ac094..00000000000 --- 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 30ec3b8db45..00000000000 --- 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 8605e2fd042..00000000000 --- 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 0b61c6e3e7c..00000000000 --- 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 a933ca609b7..00000000000 --- 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 bf9b348cde2..00000000000 --- 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 b827f6a158c..00000000000 --- 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 6b60c33a8b7..00000000000 --- 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 89ec02100a3..00000000000 --- 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 d474ceb2a4e..00000000000 --- 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 b49fdf70a6d..00000000000 --- 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 defd37c9be1..00000000000 --- 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 6b0cb9aaeba..00000000000 --- 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 d8b0c5a6d5d..00000000000 --- 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 f108f230bfd..00000000000 --- 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 36945dc5a44..00000000000 --- 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 c4cefa8e4f8..00000000000 --- 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 e89ede192ed..00000000000 --- 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 02b77334d10..00000000000 --- 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 38dd762def4..00000000000 --- 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 748fe1701d2..00000000000 --- 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 4b0a1079347..00000000000 --- 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 10c4c5c319b..00000000000 --- 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 1d0084995c7..00000000000 --- 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 dc2e28bed84..00000000000 --- 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 e32b7867a9a..00000000000 --- 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 957a08624ff..00000000000 --- 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 2c3b33089a9..00000000000 --- 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_ */ | ||
