aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-17 14:27:09 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-17 14:27:09 -0400
commitd7a20c86404bb423f843d4fe34cd1d11432892a0 (patch)
treeb194a2f1e2c6cba499f6b92088937c2d9e98d27a
parentccdbb6e96beca362db876d820ac1e560ff6d9579 (diff)
parenta4deee1ad42d93746562fe7de2149729017e3fd1 (diff)
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Included changes: - ensure RecordRoute information is added to BAT_ICMP echo_request/reply only - use VLAN_ETH_HLEN when possible - use htons when possible - substitute old fragmentation code with a new improved implementation by Martin Hundebøll - create common header for BAT_ICMP packets to improve extendibility - consider the network coding overhead when computing the overall room needed by batman headers - add dummy soft-interface rx mode handler - minor code refactoring and cleanups Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/batman-adv/Makefile2
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c14
-rw-r--r--net/batman-adv/distributed-arp-table.c11
-rw-r--r--net/batman-adv/fragmentation.c491
-rw-r--r--net/batman-adv/fragmentation.h50
-rw-r--r--net/batman-adv/gateway_client.c23
-rw-r--r--net/batman-adv/hard-interface.c22
-rw-r--r--net/batman-adv/icmp_socket.c22
-rw-r--r--net/batman-adv/main.c37
-rw-r--r--net/batman-adv/main.h10
-rw-r--r--net/batman-adv/originator.c19
-rw-r--r--net/batman-adv/packet.h79
-rw-r--r--net/batman-adv/routing.c185
-rw-r--r--net/batman-adv/routing.h4
-rw-r--r--net/batman-adv/send.c186
-rw-r--r--net/batman-adv/send.h40
-rw-r--r--net/batman-adv/soft-interface.c34
-rw-r--r--net/batman-adv/translation-table.c63
-rw-r--r--net/batman-adv/translation-table.h7
-rw-r--r--net/batman-adv/types.h70
-rw-r--r--net/batman-adv/unicast.c491
-rw-r--r--net/batman-adv/unicast.h92
22 files changed, 1105 insertions, 847 deletions
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 8ddbfe66d637..4f4aabbd8eab 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -24,6 +24,7 @@ batman-adv-y += bitarray.o
24batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o 24batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o
25batman-adv-y += debugfs.o 25batman-adv-y += debugfs.o
26batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o 26batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o
27batman-adv-y += fragmentation.o
27batman-adv-y += gateway_client.o 28batman-adv-y += gateway_client.o
28batman-adv-y += gateway_common.o 29batman-adv-y += gateway_common.o
29batman-adv-y += hard-interface.o 30batman-adv-y += hard-interface.o
@@ -37,4 +38,3 @@ batman-adv-y += send.o
37batman-adv-y += soft-interface.o 38batman-adv-y += soft-interface.o
38batman-adv-y += sysfs.o 39batman-adv-y += sysfs.o
39batman-adv-y += translation-table.o 40batman-adv-y += translation-table.o
40batman-adv-y += unicast.o
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 264de88db320..5bb58d7bdd56 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -863,25 +863,25 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
863 struct arphdr *arphdr; 863 struct arphdr *arphdr;
864 uint8_t *hw_src, *hw_dst; 864 uint8_t *hw_src, *hw_dst;
865 struct batadv_bla_claim_dst *bla_dst; 865 struct batadv_bla_claim_dst *bla_dst;
866 uint16_t proto; 866 __be16 proto;
867 int headlen; 867 int headlen;
868 unsigned short vid = BATADV_NO_FLAGS; 868 unsigned short vid = BATADV_NO_FLAGS;
869 int ret; 869 int ret;
870 870
871 ethhdr = eth_hdr(skb); 871 ethhdr = eth_hdr(skb);
872 872
873 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { 873 if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
874 vhdr = (struct vlan_ethhdr *)ethhdr; 874 vhdr = (struct vlan_ethhdr *)ethhdr;
875 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; 875 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
876 vid |= BATADV_VLAN_HAS_TAG; 876 vid |= BATADV_VLAN_HAS_TAG;
877 proto = ntohs(vhdr->h_vlan_encapsulated_proto); 877 proto = vhdr->h_vlan_encapsulated_proto;
878 headlen = sizeof(*vhdr); 878 headlen = sizeof(*vhdr);
879 } else { 879 } else {
880 proto = ntohs(ethhdr->h_proto); 880 proto = ethhdr->h_proto;
881 headlen = ETH_HLEN; 881 headlen = ETH_HLEN;
882 } 882 }
883 883
884 if (proto != ETH_P_ARP) 884 if (proto != htons(ETH_P_ARP))
885 return 0; /* not a claim frame */ 885 return 0; /* not a claim frame */
886 886
887 /* this must be a ARP frame. check if it is a claim. */ 887 /* this must be a ARP frame. check if it is a claim. */
@@ -1379,8 +1379,8 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
1379 1379
1380 ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size); 1380 ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size);
1381 1381
1382 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { 1382 if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
1383 if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr))) 1383 if (!pskb_may_pull(skb, hdr_size + VLAN_ETH_HLEN))
1384 return 0; 1384 return 0;
1385 1385
1386 vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size); 1386 vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index f07ec320dc01..99da41290f82 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -29,7 +29,6 @@
29#include "send.h" 29#include "send.h"
30#include "types.h" 30#include "types.h"
31#include "translation-table.h" 31#include "translation-table.h"
32#include "unicast.h"
33 32
34static void batadv_dat_purge(struct work_struct *work); 33static void batadv_dat_purge(struct work_struct *work);
35 34
@@ -592,9 +591,9 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
592 goto free_orig; 591 goto free_orig;
593 592
594 tmp_skb = pskb_copy(skb, GFP_ATOMIC); 593 tmp_skb = pskb_copy(skb, GFP_ATOMIC);
595 if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb, 594 if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb,
596 cand[i].orig_node, 595 cand[i].orig_node,
597 packet_subtype)) { 596 packet_subtype)) {
598 kfree_skb(tmp_skb); 597 kfree_skb(tmp_skb);
599 goto free_neigh; 598 goto free_neigh;
600 } 599 }
@@ -990,10 +989,10 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
990 * that a node not using the 4addr packet format doesn't support it. 989 * that a node not using the 4addr packet format doesn't support it.
991 */ 990 */
992 if (hdr_size == sizeof(struct batadv_unicast_4addr_packet)) 991 if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
993 err = batadv_unicast_4addr_send_skb(bat_priv, skb_new, 992 err = batadv_send_skb_unicast_4addr(bat_priv, skb_new,
994 BATADV_P_DAT_CACHE_REPLY); 993 BATADV_P_DAT_CACHE_REPLY);
995 else 994 else
996 err = batadv_unicast_send_skb(bat_priv, skb_new); 995 err = batadv_send_skb_unicast(bat_priv, skb_new);
997 996
998 if (!err) { 997 if (!err) {
999 batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX); 998 batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
new file mode 100644
index 000000000000..271d321b3a04
--- /dev/null
+++ b/net/batman-adv/fragmentation.c
@@ -0,0 +1,491 @@
1/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
2 *
3 * Martin Hundebøll <martin@hundeboll.net>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#include "main.h"
21#include "fragmentation.h"
22#include "send.h"
23#include "originator.h"
24#include "routing.h"
25#include "hard-interface.h"
26#include "soft-interface.h"
27
28
29/**
30 * batadv_frag_clear_chain - delete entries in the fragment buffer chain
31 * @head: head of chain with entries.
32 *
33 * Free fragments in the passed hlist. Should be called with appropriate lock.
34 */
35static void batadv_frag_clear_chain(struct hlist_head *head)
36{
37 struct batadv_frag_list_entry *entry;
38 struct hlist_node *node;
39
40 hlist_for_each_entry_safe(entry, node, head, list) {
41 hlist_del(&entry->list);
42 kfree_skb(entry->skb);
43 kfree(entry);
44 }
45}
46
47/**
48 * batadv_frag_purge_orig - free fragments associated to an orig
49 * @orig_node: originator to free fragments from
50 * @check_cb: optional function to tell if an entry should be purged
51 */
52void batadv_frag_purge_orig(struct batadv_orig_node *orig_node,
53 bool (*check_cb)(struct batadv_frag_table_entry *))
54{
55 struct batadv_frag_table_entry *chain;
56 uint8_t i;
57
58 for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
59 chain = &orig_node->fragments[i];
60 spin_lock_bh(&orig_node->fragments[i].lock);
61
62 if (!check_cb || check_cb(chain)) {
63 batadv_frag_clear_chain(&orig_node->fragments[i].head);
64 orig_node->fragments[i].size = 0;
65 }
66
67 spin_unlock_bh(&orig_node->fragments[i].lock);
68 }
69}
70
71/**
72 * batadv_frag_size_limit - maximum possible size of packet to be fragmented
73 *
74 * Returns the maximum size of payload that can be fragmented.
75 */
76static int batadv_frag_size_limit(void)
77{
78 int limit = BATADV_FRAG_MAX_FRAG_SIZE;
79
80 limit -= sizeof(struct batadv_frag_packet);
81 limit *= BATADV_FRAG_MAX_FRAGMENTS;
82
83 return limit;
84}
85
86/**
87 * batadv_frag_init_chain - check and prepare fragment chain for new fragment
88 * @chain: chain in fragments table to init
89 * @seqno: sequence number of the received fragment
90 *
91 * Make chain ready for a fragment with sequence number "seqno". Delete existing
92 * entries if they have an "old" sequence number.
93 *
94 * Caller must hold chain->lock.
95 *
96 * Returns true if chain is empty and caller can just insert the new fragment
97 * without searching for the right position.
98 */
99static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain,
100 uint16_t seqno)
101{
102 if (chain->seqno == seqno)
103 return false;
104
105 if (!hlist_empty(&chain->head))
106 batadv_frag_clear_chain(&chain->head);
107
108 chain->size = 0;
109 chain->seqno = seqno;
110
111 return true;
112}
113
114/**
115 * batadv_frag_insert_packet - insert a fragment into a fragment chain
116 * @orig_node: originator that the fragment was received from
117 * @skb: skb to insert
118 * @chain_out: list head to attach complete chains of fragments to
119 *
120 * Insert a new fragment into the reverse ordered chain in the right table
121 * entry. The hash table entry is cleared if "old" fragments exist in it.
122 *
123 * Returns true if skb is buffered, false on error. If the chain has all the
124 * fragments needed to merge the packet, the chain is moved to the passed head
125 * to avoid locking the chain in the table.
126 */
127static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
128 struct sk_buff *skb,
129 struct hlist_head *chain_out)
130{
131 struct batadv_frag_table_entry *chain;
132 struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr;
133 struct batadv_frag_packet *frag_packet;
134 uint8_t bucket;
135 uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet);
136 bool ret = false;
137
138 /* Linearize packet to avoid linearizing 16 packets in a row when doing
139 * the later merge. Non-linear merge should be added to remove this
140 * linearization.
141 */
142 if (skb_linearize(skb) < 0)
143 goto err;
144
145 frag_packet = (struct batadv_frag_packet *)skb->data;
146 seqno = ntohs(frag_packet->seqno);
147 bucket = seqno % BATADV_FRAG_BUFFER_COUNT;
148
149 frag_entry_new = kmalloc(sizeof(*frag_entry_new), GFP_ATOMIC);
150 if (!frag_entry_new)
151 goto err;
152
153 frag_entry_new->skb = skb;
154 frag_entry_new->no = frag_packet->no;
155
156 /* Select entry in the "chain table" and delete any prior fragments
157 * with another sequence number. batadv_frag_init_chain() returns true,
158 * if the list is empty at return.
159 */
160 chain = &orig_node->fragments[bucket];
161 spin_lock_bh(&chain->lock);
162 if (batadv_frag_init_chain(chain, seqno)) {
163 hlist_add_head(&frag_entry_new->list, &chain->head);
164 chain->size = skb->len - hdr_size;
165 chain->timestamp = jiffies;
166 ret = true;
167 goto out;
168 }
169
170 /* Find the position for the new fragment. */
171 hlist_for_each_entry(frag_entry_curr, &chain->head, list) {
172 /* Drop packet if fragment already exists. */
173 if (frag_entry_curr->no == frag_entry_new->no)
174 goto err_unlock;
175
176 /* Order fragments from highest to lowest. */
177 if (frag_entry_curr->no < frag_entry_new->no) {
178 hlist_add_before(&frag_entry_new->list,
179 &frag_entry_curr->list);
180 chain->size += skb->len - hdr_size;
181 chain->timestamp = jiffies;
182 ret = true;
183 goto out;
184 }
185 }
186
187 /* Reached the end of the list, so insert after 'frag_entry_curr'. */
188 if (likely(frag_entry_curr)) {
189 hlist_add_after(&frag_entry_curr->list, &frag_entry_new->list);
190 chain->size += skb->len - hdr_size;
191 chain->timestamp = jiffies;
192 ret = true;
193 }
194
195out:
196 if (chain->size > batadv_frag_size_limit() ||
197 ntohs(frag_packet->total_size) > batadv_frag_size_limit()) {
198 /* Clear chain if total size of either the list or the packet
199 * exceeds the maximum size of one merged packet.
200 */
201 batadv_frag_clear_chain(&chain->head);
202 chain->size = 0;
203 } else if (ntohs(frag_packet->total_size) == chain->size) {
204 /* All fragments received. Hand over chain to caller. */
205 hlist_move_list(&chain->head, chain_out);
206 chain->size = 0;
207 }
208
209err_unlock:
210 spin_unlock_bh(&chain->lock);
211
212err:
213 if (!ret)
214 kfree(frag_entry_new);
215
216 return ret;
217}
218
219/**
220 * batadv_frag_merge_packets - merge a chain of fragments
221 * @chain: head of chain with fragments
222 * @skb: packet with total size of skb after merging
223 *
224 * Expand the first skb in the chain and copy the content of the remaining
225 * skb's into the expanded one. After doing so, clear the chain.
226 *
227 * Returns the merged skb or NULL on error.
228 */
229static struct sk_buff *
230batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb)
231{
232 struct batadv_frag_packet *packet;
233 struct batadv_frag_list_entry *entry;
234 struct sk_buff *skb_out = NULL;
235 int size, hdr_size = sizeof(struct batadv_frag_packet);
236
237 /* Make sure incoming skb has non-bogus data. */
238 packet = (struct batadv_frag_packet *)skb->data;
239 size = ntohs(packet->total_size);
240 if (size > batadv_frag_size_limit())
241 goto free;
242
243 /* Remove first entry, as this is the destination for the rest of the
244 * fragments.
245 */
246 entry = hlist_entry(chain->first, struct batadv_frag_list_entry, list);
247 hlist_del(&entry->list);
248 skb_out = entry->skb;
249 kfree(entry);
250
251 /* Make room for the rest of the fragments. */
252 if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) {
253 kfree_skb(skb_out);
254 skb_out = NULL;
255 goto free;
256 }
257
258 /* Move the existing MAC header to just before the payload. (Override
259 * the fragment header.)
260 */
261 skb_pull_rcsum(skb_out, hdr_size);
262 memmove(skb_out->data - ETH_HLEN, skb_mac_header(skb_out), ETH_HLEN);
263 skb_set_mac_header(skb_out, -ETH_HLEN);
264 skb_reset_network_header(skb_out);
265 skb_reset_transport_header(skb_out);
266
267 /* Copy the payload of the each fragment into the last skb */
268 hlist_for_each_entry(entry, chain, list) {
269 size = entry->skb->len - hdr_size;
270 memcpy(skb_put(skb_out, size), entry->skb->data + hdr_size,
271 size);
272 }
273
274free:
275 /* Locking is not needed, because 'chain' is not part of any orig. */
276 batadv_frag_clear_chain(chain);
277 return skb_out;
278}
279
280/**
281 * batadv_frag_skb_buffer - buffer fragment for later merge
282 * @skb: skb to buffer
283 * @orig_node_src: originator that the skb is received from
284 *
285 * Add fragment to buffer and merge fragments if possible.
286 *
287 * There are three possible outcomes: 1) Packet is merged: Return true and
288 * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb
289 * to NULL; 3) Error: Return false and leave skb as is.
290 */
291bool batadv_frag_skb_buffer(struct sk_buff **skb,
292 struct batadv_orig_node *orig_node_src)
293{
294 struct sk_buff *skb_out = NULL;
295 struct hlist_head head = HLIST_HEAD_INIT;
296 bool ret = false;
297
298 /* Add packet to buffer and table entry if merge is possible. */
299 if (!batadv_frag_insert_packet(orig_node_src, *skb, &head))
300 goto out_err;
301
302 /* Leave if more fragments are needed to merge. */
303 if (hlist_empty(&head))
304 goto out;
305
306 skb_out = batadv_frag_merge_packets(&head, *skb);
307 if (!skb_out)
308 goto out_err;
309
310out:
311 *skb = skb_out;
312 ret = true;
313out_err:
314 return ret;
315}
316
317/**
318 * batadv_frag_skb_fwd - forward fragments that would exceed MTU when merged
319 * @skb: skb to forward
320 * @recv_if: interface that the skb is received on
321 * @orig_node_src: originator that the skb is received from
322 *
323 * Look up the next-hop of the fragments payload and check if the merged packet
324 * will exceed the MTU towards the next-hop. If so, the fragment is forwarded
325 * without merging it.
326 *
327 * Returns true if the fragment is consumed/forwarded, false otherwise.
328 */
329bool batadv_frag_skb_fwd(struct sk_buff *skb,
330 struct batadv_hard_iface *recv_if,
331 struct batadv_orig_node *orig_node_src)
332{
333 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
334 struct batadv_orig_node *orig_node_dst = NULL;
335 struct batadv_neigh_node *neigh_node = NULL;
336 struct batadv_frag_packet *packet;
337 uint16_t total_size;
338 bool ret = false;
339
340 packet = (struct batadv_frag_packet *)skb->data;
341 orig_node_dst = batadv_orig_hash_find(bat_priv, packet->dest);
342 if (!orig_node_dst)
343 goto out;
344
345 neigh_node = batadv_find_router(bat_priv, orig_node_dst, recv_if);
346 if (!neigh_node)
347 goto out;
348
349 /* Forward the fragment, if the merged packet would be too big to
350 * be assembled.
351 */
352 total_size = ntohs(packet->total_size);
353 if (total_size > neigh_node->if_incoming->net_dev->mtu) {
354 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_FWD);
355 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
356 skb->len + ETH_HLEN);
357
358 packet->header.ttl--;
359 batadv_send_skb_packet(skb, neigh_node->if_incoming,
360 neigh_node->addr);
361 ret = true;
362 }
363
364out:
365 if (orig_node_dst)
366 batadv_orig_node_free_ref(orig_node_dst);
367 if (neigh_node)
368 batadv_neigh_node_free_ref(neigh_node);
369 return ret;
370}
371
372/**
373 * batadv_frag_create - create a fragment from skb
374 * @skb: skb to create fragment from
375 * @frag_head: header to use in new fragment
376 * @mtu: size of new fragment
377 *
378 * Split the passed skb into two fragments: A new one with size matching the
379 * passed mtu and the old one with the rest. The new skb contains data from the
380 * tail of the old skb.
381 *
382 * Returns the new fragment, NULL on error.
383 */
384static struct sk_buff *batadv_frag_create(struct sk_buff *skb,
385 struct batadv_frag_packet *frag_head,
386 unsigned int mtu)
387{
388 struct sk_buff *skb_fragment;
389 unsigned header_size = sizeof(*frag_head);
390 unsigned fragment_size = mtu - header_size;
391
392 skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN);
393 if (!skb_fragment)
394 goto err;
395
396 skb->priority = TC_PRIO_CONTROL;
397
398 /* Eat the last mtu-bytes of the skb */
399 skb_reserve(skb_fragment, header_size + ETH_HLEN);
400 skb_split(skb, skb_fragment, skb->len - fragment_size);
401
402 /* Add the header */
403 skb_push(skb_fragment, header_size);
404 memcpy(skb_fragment->data, frag_head, header_size);
405
406err:
407 return skb_fragment;
408}
409
410/**
411 * batadv_frag_send_packet - create up to 16 fragments from the passed skb
412 * @skb: skb to create fragments from
413 * @orig_node: final destination of the created fragments
414 * @neigh_node: next-hop of the created fragments
415 *
416 * Returns true on success, false otherwise.
417 */
418bool batadv_frag_send_packet(struct sk_buff *skb,
419 struct batadv_orig_node *orig_node,
420 struct batadv_neigh_node *neigh_node)
421{
422 struct batadv_priv *bat_priv;
423 struct batadv_hard_iface *primary_if;
424 struct batadv_frag_packet frag_header;
425 struct sk_buff *skb_fragment;
426 unsigned mtu = neigh_node->if_incoming->net_dev->mtu;
427 unsigned header_size = sizeof(frag_header);
428 unsigned max_fragment_size, max_packet_size;
429
430 /* To avoid merge and refragmentation at next-hops we never send
431 * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
432 */
433 mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE);
434 max_fragment_size = (mtu - header_size - ETH_HLEN);
435 max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS;
436
437 /* Don't even try to fragment, if we need more than 16 fragments */
438 if (skb->len > max_packet_size)
439 goto out_err;
440
441 bat_priv = orig_node->bat_priv;
442 primary_if = batadv_primary_if_get_selected(bat_priv);
443 if (!primary_if)
444 goto out_err;
445
446 /* Create one header to be copied to all fragments */
447 frag_header.header.packet_type = BATADV_UNICAST_FRAG;
448 frag_header.header.version = BATADV_COMPAT_VERSION;
449 frag_header.header.ttl = BATADV_TTL;
450 frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
451 frag_header.reserved = 0;
452 frag_header.no = 0;
453 frag_header.total_size = htons(skb->len);
454 memcpy(frag_header.orig, primary_if->net_dev->dev_addr, ETH_ALEN);
455 memcpy(frag_header.dest, orig_node->orig, ETH_ALEN);
456
457 /* Eat and send fragments from the tail of skb */
458 while (skb->len > max_fragment_size) {
459 skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
460 if (!skb_fragment)
461 goto out_err;
462
463 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
464 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
465 skb_fragment->len + ETH_HLEN);
466 batadv_send_skb_packet(skb_fragment, neigh_node->if_incoming,
467 neigh_node->addr);
468 frag_header.no++;
469
470 /* The initial check in this function should cover this case */
471 if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1)
472 goto out_err;
473 }
474
475 /* Make room for the fragment header. */
476 if (batadv_skb_head_push(skb, header_size) < 0 ||
477 pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0)
478 goto out_err;
479
480 memcpy(skb->data, &frag_header, header_size);
481
482 /* Send the last fragment */
483 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
484 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
485 skb->len + ETH_HLEN);
486 batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
487
488 return true;
489out_err:
490 return false;
491}
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
new file mode 100644
index 000000000000..ca029e2676e7
--- /dev/null
+++ b/net/batman-adv/fragmentation.h
@@ -0,0 +1,50 @@
1/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
2 *
3 * Martin Hundebøll <martin@hundeboll.net>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#ifndef _NET_BATMAN_ADV_FRAGMENTATION_H_
21#define _NET_BATMAN_ADV_FRAGMENTATION_H_
22
23void batadv_frag_purge_orig(struct batadv_orig_node *orig,
24 bool (*check_cb)(struct batadv_frag_table_entry *));
25bool batadv_frag_skb_fwd(struct sk_buff *skb,
26 struct batadv_hard_iface *recv_if,
27 struct batadv_orig_node *orig_node_src);
28bool batadv_frag_skb_buffer(struct sk_buff **skb,
29 struct batadv_orig_node *orig_node);
30bool batadv_frag_send_packet(struct sk_buff *skb,
31 struct batadv_orig_node *orig_node,
32 struct batadv_neigh_node *neigh_node);
33
34/**
35 * batadv_frag_check_entry - check if a list of fragments has timed out
36 * @frags_entry: table entry to check
37 *
38 * Returns true if the frags entry has timed out, false otherwise.
39 */
40static inline bool
41batadv_frag_check_entry(struct batadv_frag_table_entry *frags_entry)
42{
43 if (!hlist_empty(&frags_entry->head) &&
44 batadv_has_timed_out(frags_entry->timestamp, BATADV_FRAG_TIMEOUT))
45 return true;
46 else
47 return false;
48}
49
50#endif /* _NET_BATMAN_ADV_FRAGMENTATION_H_ */
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 1bce63aa5f5f..053bb318c7a7 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -655,24 +655,29 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
655 struct iphdr *iphdr; 655 struct iphdr *iphdr;
656 struct ipv6hdr *ipv6hdr; 656 struct ipv6hdr *ipv6hdr;
657 struct udphdr *udphdr; 657 struct udphdr *udphdr;
658 struct vlan_ethhdr *vhdr;
659 __be16 proto;
658 660
659 /* check for ethernet header */ 661 /* check for ethernet header */
660 if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) 662 if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
661 return false; 663 return false;
662 ethhdr = (struct ethhdr *)skb->data; 664 ethhdr = (struct ethhdr *)skb->data;
665 proto = ethhdr->h_proto;
663 *header_len += ETH_HLEN; 666 *header_len += ETH_HLEN;
664 667
665 /* check for initial vlan header */ 668 /* check for initial vlan header */
666 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { 669 if (proto == htons(ETH_P_8021Q)) {
667 if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) 670 if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
668 return false; 671 return false;
669 ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); 672
673 vhdr = (struct vlan_ethhdr *)skb->data;
674 proto = vhdr->h_vlan_encapsulated_proto;
670 *header_len += VLAN_HLEN; 675 *header_len += VLAN_HLEN;
671 } 676 }
672 677
673 /* check for ip header */ 678 /* check for ip header */
674 switch (ntohs(ethhdr->h_proto)) { 679 switch (proto) {
675 case ETH_P_IP: 680 case htons(ETH_P_IP):
676 if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) 681 if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
677 return false; 682 return false;
678 iphdr = (struct iphdr *)(skb->data + *header_len); 683 iphdr = (struct iphdr *)(skb->data + *header_len);
@@ -683,7 +688,7 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
683 return false; 688 return false;
684 689
685 break; 690 break;
686 case ETH_P_IPV6: 691 case htons(ETH_P_IPV6):
687 if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) 692 if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
688 return false; 693 return false;
689 ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); 694 ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
@@ -710,12 +715,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
710 *header_len += sizeof(*udphdr); 715 *header_len += sizeof(*udphdr);
711 716
712 /* check for bootp port */ 717 /* check for bootp port */
713 if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && 718 if ((proto == htons(ETH_P_IP)) &&
714 (ntohs(udphdr->dest) != 67)) 719 (udphdr->dest != htons(67)))
715 return false; 720 return false;
716 721
717 if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && 722 if ((proto == htons(ETH_P_IPV6)) &&
718 (ntohs(udphdr->dest) != 547)) 723 (udphdr->dest != htons(547)))
719 return false; 724 return false;
720 725
721 return true; 726 return true;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index eeb667112d64..d564af295db4 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -269,9 +269,10 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
269 const struct batadv_priv *bat_priv = netdev_priv(soft_iface); 269 const struct batadv_priv *bat_priv = netdev_priv(soft_iface);
270 const struct batadv_hard_iface *hard_iface; 270 const struct batadv_hard_iface *hard_iface;
271 /* allow big frames if all devices are capable to do so 271 /* allow big frames if all devices are capable to do so
272 * (have MTU > 1500 + BAT_HEADER_LEN) 272 * (have MTU > 1500 + batadv_max_header_len())
273 */ 273 */
274 int min_mtu = ETH_DATA_LEN; 274 int min_mtu = ETH_DATA_LEN;
275 int max_header_len = batadv_max_header_len();
275 276
276 if (atomic_read(&bat_priv->fragmentation)) 277 if (atomic_read(&bat_priv->fragmentation))
277 goto out; 278 goto out;
@@ -285,8 +286,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
285 if (hard_iface->soft_iface != soft_iface) 286 if (hard_iface->soft_iface != soft_iface)
286 continue; 287 continue;
287 288
288 min_mtu = min_t(int, 289 min_mtu = min_t(int, hard_iface->net_dev->mtu - max_header_len,
289 hard_iface->net_dev->mtu - BATADV_HEADER_LEN,
290 min_mtu); 290 min_mtu);
291 } 291 }
292 rcu_read_unlock(); 292 rcu_read_unlock();
@@ -379,7 +379,8 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
379{ 379{
380 struct batadv_priv *bat_priv; 380 struct batadv_priv *bat_priv;
381 struct net_device *soft_iface, *master; 381 struct net_device *soft_iface, *master;
382 __be16 ethertype = __constant_htons(ETH_P_BATMAN); 382 __be16 ethertype = htons(ETH_P_BATMAN);
383 int max_header_len = batadv_max_header_len();
383 int ret; 384 int ret;
384 385
385 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 386 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
@@ -444,23 +445,22 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
444 hard_iface->batman_adv_ptype.dev = hard_iface->net_dev; 445 hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
445 dev_add_pack(&hard_iface->batman_adv_ptype); 446 dev_add_pack(&hard_iface->batman_adv_ptype);
446 447
447 atomic_set(&hard_iface->frag_seqno, 1);
448 batadv_info(hard_iface->soft_iface, "Adding interface: %s\n", 448 batadv_info(hard_iface->soft_iface, "Adding interface: %s\n",
449 hard_iface->net_dev->name); 449 hard_iface->net_dev->name);
450 450
451 if (atomic_read(&bat_priv->fragmentation) && 451 if (atomic_read(&bat_priv->fragmentation) &&
452 hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN) 452 hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
453 batadv_info(hard_iface->soft_iface, 453 batadv_info(hard_iface->soft_iface,
454 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %zi would solve the problem.\n", 454 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %i would solve the problem.\n",
455 hard_iface->net_dev->name, hard_iface->net_dev->mtu, 455 hard_iface->net_dev->name, hard_iface->net_dev->mtu,
456 ETH_DATA_LEN + BATADV_HEADER_LEN); 456 ETH_DATA_LEN + max_header_len);
457 457
458 if (!atomic_read(&bat_priv->fragmentation) && 458 if (!atomic_read(&bat_priv->fragmentation) &&
459 hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN) 459 hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
460 batadv_info(hard_iface->soft_iface, 460 batadv_info(hard_iface->soft_iface,
461 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %zi.\n", 461 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %i.\n",
462 hard_iface->net_dev->name, hard_iface->net_dev->mtu, 462 hard_iface->net_dev->name, hard_iface->net_dev->mtu,
463 ETH_DATA_LEN + BATADV_HEADER_LEN); 463 ETH_DATA_LEN + max_header_len);
464 464
465 if (batadv_hardif_is_iface_up(hard_iface)) 465 if (batadv_hardif_is_iface_up(hard_iface))
466 batadv_hardif_activate_interface(hard_iface); 466 batadv_hardif_activate_interface(hard_iface);
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 5a99bb4b6b82..82ac6472fa6f 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -192,25 +192,25 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
192 goto free_skb; 192 goto free_skb;
193 } 193 }
194 194
195 if (icmp_packet->header.packet_type != BATADV_ICMP) { 195 if (icmp_packet->icmph.header.packet_type != BATADV_ICMP) {
196 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 196 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
197 "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n"); 197 "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
198 len = -EINVAL; 198 len = -EINVAL;
199 goto free_skb; 199 goto free_skb;
200 } 200 }
201 201
202 if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { 202 if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
203 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 203 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
204 "Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n"); 204 "Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
205 len = -EINVAL; 205 len = -EINVAL;
206 goto free_skb; 206 goto free_skb;
207 } 207 }
208 208
209 icmp_packet->uid = socket_client->index; 209 icmp_packet->icmph.uid = socket_client->index;
210 210
211 if (icmp_packet->header.version != BATADV_COMPAT_VERSION) { 211 if (icmp_packet->icmph.header.version != BATADV_COMPAT_VERSION) {
212 icmp_packet->msg_type = BATADV_PARAMETER_PROBLEM; 212 icmp_packet->icmph.msg_type = BATADV_PARAMETER_PROBLEM;
213 icmp_packet->header.version = BATADV_COMPAT_VERSION; 213 icmp_packet->icmph.header.version = BATADV_COMPAT_VERSION;
214 batadv_socket_add_packet(socket_client, icmp_packet, 214 batadv_socket_add_packet(socket_client, icmp_packet,
215 packet_len); 215 packet_len);
216 goto free_skb; 216 goto free_skb;
@@ -219,7 +219,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
219 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) 219 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
220 goto dst_unreach; 220 goto dst_unreach;
221 221
222 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->dst); 222 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.dst);
223 if (!orig_node) 223 if (!orig_node)
224 goto dst_unreach; 224 goto dst_unreach;
225 225
@@ -233,7 +233,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
233 if (neigh_node->if_incoming->if_status != BATADV_IF_ACTIVE) 233 if (neigh_node->if_incoming->if_status != BATADV_IF_ACTIVE)
234 goto dst_unreach; 234 goto dst_unreach;
235 235
236 memcpy(icmp_packet->orig, 236 memcpy(icmp_packet->icmph.orig,
237 primary_if->net_dev->dev_addr, ETH_ALEN); 237 primary_if->net_dev->dev_addr, ETH_ALEN);
238 238
239 if (packet_len == sizeof(struct batadv_icmp_packet_rr)) 239 if (packet_len == sizeof(struct batadv_icmp_packet_rr))
@@ -244,7 +244,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
244 goto out; 244 goto out;
245 245
246dst_unreach: 246dst_unreach:
247 icmp_packet->msg_type = BATADV_DESTINATION_UNREACHABLE; 247 icmp_packet->icmph.msg_type = BATADV_DESTINATION_UNREACHABLE;
248 batadv_socket_add_packet(socket_client, icmp_packet, packet_len); 248 batadv_socket_add_packet(socket_client, icmp_packet, packet_len);
249free_skb: 249free_skb:
250 kfree_skb(skb); 250 kfree_skb(skb);
@@ -318,7 +318,7 @@ static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
318 /* while waiting for the lock the socket_client could have been 318 /* while waiting for the lock the socket_client could have been
319 * deleted 319 * deleted
320 */ 320 */
321 if (!batadv_socket_client_hash[icmp_packet->uid]) { 321 if (!batadv_socket_client_hash[icmp_packet->icmph.uid]) {
322 spin_unlock_bh(&socket_client->lock); 322 spin_unlock_bh(&socket_client->lock);
323 kfree(socket_packet); 323 kfree(socket_packet);
324 return; 324 return;
@@ -347,7 +347,7 @@ void batadv_socket_receive_packet(struct batadv_icmp_packet_rr *icmp_packet,
347{ 347{
348 struct batadv_socket_client *hash; 348 struct batadv_socket_client *hash;
349 349
350 hash = batadv_socket_client_hash[icmp_packet->uid]; 350 hash = batadv_socket_client_hash[icmp_packet->icmph.uid];
351 if (hash) 351 if (hash)
352 batadv_socket_add_packet(hash, icmp_packet, icmp_len); 352 batadv_socket_add_packet(hash, icmp_packet, icmp_len);
353} 353}
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 8b195e63e70e..7f3a5c426615 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -36,11 +36,11 @@
36#include "gateway_client.h" 36#include "gateway_client.h"
37#include "bridge_loop_avoidance.h" 37#include "bridge_loop_avoidance.h"
38#include "distributed-arp-table.h" 38#include "distributed-arp-table.h"
39#include "unicast.h"
40#include "gateway_common.h" 39#include "gateway_common.h"
41#include "hash.h" 40#include "hash.h"
42#include "bat_algo.h" 41#include "bat_algo.h"
43#include "network-coding.h" 42#include "network-coding.h"
43#include "fragmentation.h"
44 44
45 45
46/* List manipulations on hardif_list have to be rtnl_lock()'ed, 46/* List manipulations on hardif_list have to be rtnl_lock()'ed,
@@ -256,6 +256,31 @@ out:
256} 256}
257 257
258/** 258/**
259 * batadv_max_header_len - calculate maximum encapsulation overhead for a
260 * payload packet
261 *
262 * Return the maximum encapsulation overhead in bytes.
263 */
264int batadv_max_header_len(void)
265{
266 int header_len = 0;
267
268 header_len = max_t(int, header_len,
269 sizeof(struct batadv_unicast_packet));
270 header_len = max_t(int, header_len,
271 sizeof(struct batadv_unicast_4addr_packet));
272 header_len = max_t(int, header_len,
273 sizeof(struct batadv_bcast_packet));
274
275#ifdef CONFIG_BATMAN_ADV_NC
276 header_len = max_t(int, header_len,
277 sizeof(struct batadv_coded_packet));
278#endif
279
280 return header_len;
281}
282
283/**
259 * batadv_skb_set_priority - sets skb priority according to packet content 284 * batadv_skb_set_priority - sets skb priority according to packet content
260 * @skb: the packet to be sent 285 * @skb: the packet to be sent
261 * @offset: offset to the packet content 286 * @offset: offset to the packet content
@@ -399,10 +424,10 @@ static void batadv_recv_handler_init(void)
399 /* compile time checks for struct member offsets */ 424 /* compile time checks for struct member offsets */
400 BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10); 425 BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
401 BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4); 426 BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
402 BUILD_BUG_ON(offsetof(struct batadv_unicast_frag_packet, dest) != 4);
403 BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4); 427 BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
404 BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4); 428 BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
405 BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4); 429 BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
430 BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
406 431
407 /* broadcast packet */ 432 /* broadcast packet */
408 batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; 433 batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@ -412,12 +437,12 @@ static void batadv_recv_handler_init(void)
412 batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet; 437 batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
413 /* unicast packet */ 438 /* unicast packet */
414 batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet; 439 batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
415 /* fragmented unicast packet */
416 batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
417 /* unicast tvlv packet */ 440 /* unicast tvlv packet */
418 batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv; 441 batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
419 /* batman icmp packet */ 442 /* batman icmp packet */
420 batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet; 443 batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
444 /* Fragmented packets */
445 batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_frag_packet;
421} 446}
422 447
423int 448int
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index e11c2ec7a739..54c13d51edbe 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -131,6 +131,15 @@ enum batadv_uev_type {
131 131
132#define BATADV_GW_THRESHOLD 50 132#define BATADV_GW_THRESHOLD 50
133 133
134/* Number of fragment chains for each orig_node */
135#define BATADV_FRAG_BUFFER_COUNT 8
136/* Maximum number of fragments for one packet */
137#define BATADV_FRAG_MAX_FRAGMENTS 16
138/* Maxumim size of each fragment */
139#define BATADV_FRAG_MAX_FRAG_SIZE 1400
140/* Time to keep fragments while waiting for rest of the fragments */
141#define BATADV_FRAG_TIMEOUT 10000
142
134#define BATADV_DAT_CANDIDATE_NOT_FOUND 0 143#define BATADV_DAT_CANDIDATE_NOT_FOUND 0
135#define BATADV_DAT_CANDIDATE_ORIG 1 144#define BATADV_DAT_CANDIDATE_ORIG 1
136 145
@@ -182,6 +191,7 @@ void batadv_mesh_free(struct net_device *soft_iface);
182int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr); 191int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr);
183struct batadv_hard_iface * 192struct batadv_hard_iface *
184batadv_seq_print_text_primary_if_get(struct seq_file *seq); 193batadv_seq_print_text_primary_if_get(struct seq_file *seq);
194int batadv_max_header_len(void);
185void batadv_skb_set_priority(struct sk_buff *skb, int offset); 195void batadv_skb_set_priority(struct sk_buff *skb, int offset);
186int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, 196int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
187 struct packet_type *ptype, 197 struct packet_type *ptype,
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 5d53d2f38377..a591dc5c321e 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -25,10 +25,10 @@
25#include "routing.h" 25#include "routing.h"
26#include "gateway_client.h" 26#include "gateway_client.h"
27#include "hard-interface.h" 27#include "hard-interface.h"
28#include "unicast.h"
29#include "soft-interface.h" 28#include "soft-interface.h"
30#include "bridge_loop_avoidance.h" 29#include "bridge_loop_avoidance.h"
31#include "network-coding.h" 30#include "network-coding.h"
31#include "fragmentation.h"
32 32
33/* hash class keys */ 33/* hash class keys */
34static struct lock_class_key batadv_orig_hash_lock_class_key; 34static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -146,7 +146,8 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
146 /* Free nc_nodes */ 146 /* Free nc_nodes */
147 batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); 147 batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
148 148
149 batadv_frag_list_free(&orig_node->frag_list); 149 batadv_frag_purge_orig(orig_node, NULL);
150
150 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, 151 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node,
151 "originator timed out"); 152 "originator timed out");
152 153
@@ -217,7 +218,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
217 const uint8_t *addr) 218 const uint8_t *addr)
218{ 219{
219 struct batadv_orig_node *orig_node; 220 struct batadv_orig_node *orig_node;
220 int size; 221 int size, i;
221 int hash_added; 222 int hash_added;
222 unsigned long reset_time; 223 unsigned long reset_time;
223 224
@@ -269,8 +270,11 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
269 size = bat_priv->num_ifaces * sizeof(uint8_t); 270 size = bat_priv->num_ifaces * sizeof(uint8_t);
270 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); 271 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
271 272
272 INIT_LIST_HEAD(&orig_node->frag_list); 273 for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
273 orig_node->last_frag_packet = 0; 274 INIT_HLIST_HEAD(&orig_node->fragments[i].head);
275 spin_lock_init(&orig_node->fragments[i].lock);
276 orig_node->fragments[i].size = 0;
277 }
274 278
275 if (!orig_node->bcast_own_sum) 279 if (!orig_node->bcast_own_sum)
276 goto free_bcast_own; 280 goto free_bcast_own;
@@ -394,9 +398,8 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
394 continue; 398 continue;
395 } 399 }
396 400
397 if (batadv_has_timed_out(orig_node->last_frag_packet, 401 batadv_frag_purge_orig(orig_node,
398 BATADV_FRAG_TIMEOUT)) 402 batadv_frag_check_entry);
399 batadv_frag_list_free(&orig_node->frag_list);
400 } 403 }
401 spin_unlock_bh(list_lock); 404 spin_unlock_bh(list_lock);
402 } 405 }
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 4361bae6186a..65e723ed030b 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -91,12 +91,6 @@ enum batadv_icmp_packettype {
91 BATADV_PARAMETER_PROBLEM = 12, 91 BATADV_PARAMETER_PROBLEM = 12,
92}; 92};
93 93
94/* fragmentation defines */
95enum batadv_unicast_frag_flags {
96 BATADV_UNI_FRAG_HEAD = BIT(0),
97 BATADV_UNI_FRAG_LARGETAIL = BIT(1),
98};
99
100/* tt data subtypes */ 94/* tt data subtypes */
101#define BATADV_TT_DATA_TYPE_MASK 0x0F 95#define BATADV_TT_DATA_TYPE_MASK 0x0F
102 96
@@ -192,29 +186,47 @@ struct batadv_ogm_packet {
192 186
193#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) 187#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
194 188
195struct batadv_icmp_packet { 189/**
190 * batadv_icmp_header - common ICMP header
191 * @header: common batman header
192 * @msg_type: ICMP packet type
193 * @dst: address of the destination node
194 * @orig: address of the source node
195 * @uid: local ICMP socket identifier
196 */
197struct batadv_icmp_header {
196 struct batadv_header header; 198 struct batadv_header header;
197 uint8_t msg_type; /* see ICMP message types above */ 199 uint8_t msg_type; /* see ICMP message types above */
198 uint8_t dst[ETH_ALEN]; 200 uint8_t dst[ETH_ALEN];
199 uint8_t orig[ETH_ALEN]; 201 uint8_t orig[ETH_ALEN];
200 __be16 seqno;
201 uint8_t uid; 202 uint8_t uid;
203};
204
205/**
206 * batadv_icmp_packet - ICMP packet
207 * @icmph: common ICMP header
208 * @reserved: not used - useful for alignment
209 * @seqno: ICMP sequence number
210 */
211struct batadv_icmp_packet {
212 struct batadv_icmp_header icmph;
202 uint8_t reserved; 213 uint8_t reserved;
214 __be16 seqno;
203}; 215};
204 216
205#define BATADV_RR_LEN 16 217#define BATADV_RR_LEN 16
206 218
207/* icmp_packet_rr must start with all fields from imcp_packet 219/**
208 * as this is assumed by code that handles ICMP packets 220 * batadv_icmp_packet_rr - ICMP RouteRecord packet
221 * @icmph: common ICMP header
222 * @rr_cur: number of entries the rr array
223 * @seqno: ICMP sequence number
224 * @rr: route record array
209 */ 225 */
210struct batadv_icmp_packet_rr { 226struct batadv_icmp_packet_rr {
211 struct batadv_header header; 227 struct batadv_icmp_header icmph;
212 uint8_t msg_type; /* see ICMP message types above */
213 uint8_t dst[ETH_ALEN];
214 uint8_t orig[ETH_ALEN];
215 __be16 seqno;
216 uint8_t uid;
217 uint8_t rr_cur; 228 uint8_t rr_cur;
229 __be16 seqno;
218 uint8_t rr[BATADV_RR_LEN][ETH_ALEN]; 230 uint8_t rr[BATADV_RR_LEN][ETH_ALEN];
219}; 231};
220 232
@@ -255,15 +267,32 @@ struct batadv_unicast_4addr_packet {
255 */ 267 */
256}; 268};
257 269
258struct batadv_unicast_frag_packet { 270/**
259 struct batadv_header header; 271 * struct batadv_frag_packet - fragmented packet
260 uint8_t ttvn; /* destination translation table version number */ 272 * @header: common batman packet header with type, compatversion, and ttl
261 uint8_t dest[ETH_ALEN]; 273 * @dest: final destination used when routing fragments
262 uint8_t flags; 274 * @orig: originator of the fragment used when merging the packet
263 uint8_t align; 275 * @no: fragment number within this sequence
264 uint8_t orig[ETH_ALEN]; 276 * @reserved: reserved byte for alignment
265 __be16 seqno; 277 * @seqno: sequence identification
266} __packed; 278 * @total_size: size of the merged packet
279 */
280struct batadv_frag_packet {
281 struct batadv_header header;
282#if defined(__BIG_ENDIAN_BITFIELD)
283 uint8_t no:4;
284 uint8_t reserved:4;
285#elif defined(__LITTLE_ENDIAN_BITFIELD)
286 uint8_t reserved:4;
287 uint8_t no:4;
288#else
289#error "unknown bitfield endianess"
290#endif
291 uint8_t dest[ETH_ALEN];
292 uint8_t orig[ETH_ALEN];
293 __be16 seqno;
294 __be16 total_size;
295};
267 296
268struct batadv_bcast_packet { 297struct batadv_bcast_packet {
269 struct batadv_header header; 298 struct batadv_header header;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 457dfef9c5fc..3281a504c20a 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -25,10 +25,10 @@
25#include "icmp_socket.h" 25#include "icmp_socket.h"
26#include "translation-table.h" 26#include "translation-table.h"
27#include "originator.h" 27#include "originator.h"
28#include "unicast.h"
29#include "bridge_loop_avoidance.h" 28#include "bridge_loop_avoidance.h"
30#include "distributed-arp-table.h" 29#include "distributed-arp-table.h"
31#include "network-coding.h" 30#include "network-coding.h"
31#include "fragmentation.h"
32 32
33static int batadv_route_unicast_packet(struct sk_buff *skb, 33static int batadv_route_unicast_packet(struct sk_buff *skb,
34 struct batadv_hard_iface *recv_if); 34 struct batadv_hard_iface *recv_if);
@@ -258,7 +258,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
258 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 258 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
259 259
260 /* add data to device queue */ 260 /* add data to device queue */
261 if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { 261 if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
262 batadv_socket_receive_packet(icmp_packet, icmp_len); 262 batadv_socket_receive_packet(icmp_packet, icmp_len);
263 goto out; 263 goto out;
264 } 264 }
@@ -269,7 +269,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
269 269
270 /* answer echo request (ping) */ 270 /* answer echo request (ping) */
271 /* get routing information */ 271 /* get routing information */
272 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); 272 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
273 if (!orig_node) 273 if (!orig_node)
274 goto out; 274 goto out;
275 275
@@ -279,10 +279,11 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
279 279
280 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 280 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
281 281
282 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 282 memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
283 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); 283 memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
284 icmp_packet->msg_type = BATADV_ECHO_REPLY; 284 ETH_ALEN);
285 icmp_packet->header.ttl = BATADV_TTL; 285 icmp_packet->icmph.msg_type = BATADV_ECHO_REPLY;
286 icmp_packet->icmph.header.ttl = BATADV_TTL;
286 287
287 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 288 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
288 ret = NET_RX_SUCCESS; 289 ret = NET_RX_SUCCESS;
@@ -306,9 +307,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
306 icmp_packet = (struct batadv_icmp_packet *)skb->data; 307 icmp_packet = (struct batadv_icmp_packet *)skb->data;
307 308
308 /* send TTL exceeded if packet is an echo request (traceroute) */ 309 /* send TTL exceeded if packet is an echo request (traceroute) */
309 if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { 310 if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
310 pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n", 311 pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
311 icmp_packet->orig, icmp_packet->dst); 312 icmp_packet->icmph.orig, icmp_packet->icmph.dst);
312 goto out; 313 goto out;
313 } 314 }
314 315
@@ -317,7 +318,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
317 goto out; 318 goto out;
318 319
319 /* get routing information */ 320 /* get routing information */
320 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); 321 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
321 if (!orig_node) 322 if (!orig_node)
322 goto out; 323 goto out;
323 324
@@ -327,10 +328,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
327 328
328 icmp_packet = (struct batadv_icmp_packet *)skb->data; 329 icmp_packet = (struct batadv_icmp_packet *)skb->data;
329 330
330 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 331 memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
331 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); 332 memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
332 icmp_packet->msg_type = BATADV_TTL_EXCEEDED; 333 ETH_ALEN);
333 icmp_packet->header.ttl = BATADV_TTL; 334 icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
335 icmp_packet->icmph.header.ttl = BATADV_TTL;
334 336
335 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 337 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
336 ret = NET_RX_SUCCESS; 338 ret = NET_RX_SUCCESS;
@@ -379,7 +381,9 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
379 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 381 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
380 382
381 /* add record route information if not full */ 383 /* add record route information if not full */
382 if ((hdr_size == sizeof(struct batadv_icmp_packet_rr)) && 384 if ((icmp_packet->icmph.msg_type == BATADV_ECHO_REPLY ||
385 icmp_packet->icmph.msg_type == BATADV_ECHO_REQUEST) &&
386 (hdr_size == sizeof(struct batadv_icmp_packet_rr)) &&
383 (icmp_packet->rr_cur < BATADV_RR_LEN)) { 387 (icmp_packet->rr_cur < BATADV_RR_LEN)) {
384 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]), 388 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
385 ethhdr->h_dest, ETH_ALEN); 389 ethhdr->h_dest, ETH_ALEN);
@@ -387,15 +391,15 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
387 } 391 }
388 392
389 /* packet for me */ 393 /* packet for me */
390 if (batadv_is_my_mac(bat_priv, icmp_packet->dst)) 394 if (batadv_is_my_mac(bat_priv, icmp_packet->icmph.dst))
391 return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size); 395 return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size);
392 396
393 /* TTL exceeded */ 397 /* TTL exceeded */
394 if (icmp_packet->header.ttl < 2) 398 if (icmp_packet->icmph.header.ttl < 2)
395 return batadv_recv_icmp_ttl_exceeded(bat_priv, skb); 399 return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
396 400
397 /* get routing information */ 401 /* get routing information */
398 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->dst); 402 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.dst);
399 if (!orig_node) 403 if (!orig_node)
400 goto out; 404 goto out;
401 405
@@ -406,7 +410,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
406 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 410 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
407 411
408 /* decrement ttl */ 412 /* decrement ttl */
409 icmp_packet->header.ttl--; 413 icmp_packet->icmph.header.ttl--;
410 414
411 /* route it */ 415 /* route it */
412 if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP) 416 if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -651,11 +655,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
651{ 655{
652 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 656 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
653 struct batadv_orig_node *orig_node = NULL; 657 struct batadv_orig_node *orig_node = NULL;
654 struct batadv_neigh_node *neigh_node = NULL;
655 struct batadv_unicast_packet *unicast_packet; 658 struct batadv_unicast_packet *unicast_packet;
656 struct ethhdr *ethhdr = eth_hdr(skb); 659 struct ethhdr *ethhdr = eth_hdr(skb);
657 int res, hdr_len, ret = NET_RX_DROP; 660 int res, hdr_len, ret = NET_RX_DROP;
658 struct sk_buff *new_skb;
659 661
660 unicast_packet = (struct batadv_unicast_packet *)skb->data; 662 unicast_packet = (struct batadv_unicast_packet *)skb->data;
661 663
@@ -672,46 +674,12 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
672 if (!orig_node) 674 if (!orig_node)
673 goto out; 675 goto out;
674 676
675 /* find_router() increases neigh_nodes refcount if found. */
676 neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
677
678 if (!neigh_node)
679 goto out;
680
681 /* create a copy of the skb, if needed, to modify it. */ 677 /* create a copy of the skb, if needed, to modify it. */
682 if (skb_cow(skb, ETH_HLEN) < 0) 678 if (skb_cow(skb, ETH_HLEN) < 0)
683 goto out; 679 goto out;
684 680
685 unicast_packet = (struct batadv_unicast_packet *)skb->data;
686
687 if (unicast_packet->header.packet_type == BATADV_UNICAST &&
688 atomic_read(&bat_priv->fragmentation) &&
689 skb->len > neigh_node->if_incoming->net_dev->mtu) {
690 ret = batadv_frag_send_skb(skb, bat_priv,
691 neigh_node->if_incoming,
692 neigh_node->addr);
693 goto out;
694 }
695
696 if (unicast_packet->header.packet_type == BATADV_UNICAST_FRAG &&
697 batadv_frag_can_reassemble(skb,
698 neigh_node->if_incoming->net_dev->mtu)) {
699 ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
700
701 if (ret == NET_RX_DROP)
702 goto out;
703
704 /* packet was buffered for late merge */
705 if (!new_skb) {
706 ret = NET_RX_SUCCESS;
707 goto out;
708 }
709
710 skb = new_skb;
711 unicast_packet = (struct batadv_unicast_packet *)skb->data;
712 }
713
714 /* decrement ttl */ 681 /* decrement ttl */
682 unicast_packet = (struct batadv_unicast_packet *)skb->data;
715 unicast_packet->header.ttl--; 683 unicast_packet->header.ttl--;
716 684
717 switch (unicast_packet->header.packet_type) { 685 switch (unicast_packet->header.packet_type) {
@@ -746,8 +714,6 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
746 } 714 }
747 715
748out: 716out:
749 if (neigh_node)
750 batadv_neigh_node_free_ref(neigh_node);
751 if (orig_node) 717 if (orig_node)
752 batadv_orig_node_free_ref(orig_node); 718 batadv_orig_node_free_ref(orig_node);
753 return ret; 719 return ret;
@@ -1001,51 +967,6 @@ rx_success:
1001 return batadv_route_unicast_packet(skb, recv_if); 967 return batadv_route_unicast_packet(skb, recv_if);
1002} 968}
1003 969
1004int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
1005 struct batadv_hard_iface *recv_if)
1006{
1007 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1008 struct batadv_unicast_frag_packet *unicast_packet;
1009 int hdr_size = sizeof(*unicast_packet);
1010 struct sk_buff *new_skb = NULL;
1011 int ret;
1012
1013 if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
1014 return NET_RX_DROP;
1015
1016 if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
1017 return NET_RX_DROP;
1018
1019 unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
1020
1021 /* packet for me */
1022 if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
1023 ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
1024
1025 if (ret == NET_RX_DROP)
1026 return NET_RX_DROP;
1027
1028 /* packet was buffered for late merge */
1029 if (!new_skb)
1030 return NET_RX_SUCCESS;
1031
1032 if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
1033 hdr_size))
1034 goto rx_success;
1035 if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
1036 hdr_size))
1037 goto rx_success;
1038
1039 batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
1040 sizeof(struct batadv_unicast_packet), NULL);
1041
1042rx_success:
1043 return NET_RX_SUCCESS;
1044 }
1045
1046 return batadv_route_unicast_packet(skb, recv_if);
1047}
1048
1049/** 970/**
1050 * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets 971 * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
1051 * @skb: unicast tvlv packet to process 972 * @skb: unicast tvlv packet to process
@@ -1095,6 +1016,64 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
1095 return ret; 1016 return ret;
1096} 1017}
1097 1018
1019/**
1020 * batadv_recv_frag_packet - process received fragment
1021 * @skb: the received fragment
1022 * @recv_if: interface that the skb is received on
1023 *
1024 * This function does one of the three following things: 1) Forward fragment, if
1025 * the assembled packet will exceed our MTU; 2) Buffer fragment, if we till
1026 * lack further fragments; 3) Merge fragments, if we have all needed parts.
1027 *
1028 * Return NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
1029 */
1030int batadv_recv_frag_packet(struct sk_buff *skb,
1031 struct batadv_hard_iface *recv_if)
1032{
1033 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1034 struct batadv_orig_node *orig_node_src = NULL;
1035 struct batadv_frag_packet *frag_packet;
1036 int ret = NET_RX_DROP;
1037
1038 if (batadv_check_unicast_packet(bat_priv, skb,
1039 sizeof(*frag_packet)) < 0)
1040 goto out;
1041
1042 frag_packet = (struct batadv_frag_packet *)skb->data;
1043 orig_node_src = batadv_orig_hash_find(bat_priv, frag_packet->orig);
1044 if (!orig_node_src)
1045 goto out;
1046
1047 /* Route the fragment if it is not for us and too big to be merged. */
1048 if (!batadv_is_my_mac(bat_priv, frag_packet->dest) &&
1049 batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) {
1050 ret = NET_RX_SUCCESS;
1051 goto out;
1052 }
1053
1054 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX);
1055 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len);
1056
1057 /* Add fragment to buffer and merge if possible. */
1058 if (!batadv_frag_skb_buffer(&skb, orig_node_src))
1059 goto out;
1060
1061 /* Deliver merged packet to the appropriate handler, if it was
1062 * merged
1063 */
1064 if (skb)
1065 batadv_batman_skb_recv(skb, recv_if->net_dev,
1066 &recv_if->batman_adv_ptype, NULL);
1067
1068 ret = NET_RX_SUCCESS;
1069
1070out:
1071 if (orig_node_src)
1072 batadv_orig_node_free_ref(orig_node_src);
1073
1074 return ret;
1075}
1076
1098int batadv_recv_bcast_packet(struct sk_buff *skb, 1077int batadv_recv_bcast_packet(struct sk_buff *skb,
1099 struct batadv_hard_iface *recv_if) 1078 struct batadv_hard_iface *recv_if)
1100{ 1079{
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index ea15fa6302ad..55d637a90621 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -30,8 +30,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
30 struct batadv_hard_iface *recv_if); 30 struct batadv_hard_iface *recv_if);
31int batadv_recv_unicast_packet(struct sk_buff *skb, 31int batadv_recv_unicast_packet(struct sk_buff *skb,
32 struct batadv_hard_iface *recv_if); 32 struct batadv_hard_iface *recv_if);
33int batadv_recv_ucast_frag_packet(struct sk_buff *skb, 33int batadv_recv_frag_packet(struct sk_buff *skb,
34 struct batadv_hard_iface *recv_if); 34 struct batadv_hard_iface *iface);
35int batadv_recv_bcast_packet(struct sk_buff *skb, 35int batadv_recv_bcast_packet(struct sk_buff *skb,
36 struct batadv_hard_iface *recv_if); 36 struct batadv_hard_iface *recv_if);
37int batadv_recv_tt_query(struct sk_buff *skb, 37int batadv_recv_tt_query(struct sk_buff *skb,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 81d69fb97c17..82588e425641 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -25,10 +25,10 @@
25#include "soft-interface.h" 25#include "soft-interface.h"
26#include "hard-interface.h" 26#include "hard-interface.h"
27#include "gateway_common.h" 27#include "gateway_common.h"
28#include "gateway_client.h"
28#include "originator.h" 29#include "originator.h"
29#include "network-coding.h" 30#include "network-coding.h"
30 31#include "fragmentation.h"
31#include <linux/if_ether.h>
32 32
33static void batadv_send_outstanding_bcast_packet(struct work_struct *work); 33static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
34 34
@@ -63,10 +63,10 @@ int batadv_send_skb_packet(struct sk_buff *skb,
63 ethhdr = eth_hdr(skb); 63 ethhdr = eth_hdr(skb);
64 memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN); 64 memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN);
65 memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN); 65 memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
66 ethhdr->h_proto = __constant_htons(ETH_P_BATMAN); 66 ethhdr->h_proto = htons(ETH_P_BATMAN);
67 67
68 skb_set_network_header(skb, ETH_HLEN); 68 skb_set_network_header(skb, ETH_HLEN);
69 skb->protocol = __constant_htons(ETH_P_BATMAN); 69 skb->protocol = htons(ETH_P_BATMAN);
70 70
71 skb->dev = hard_iface->net_dev; 71 skb->dev = hard_iface->net_dev;
72 72
@@ -108,7 +108,19 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
108 /* batadv_find_router() increases neigh_nodes refcount if found. */ 108 /* batadv_find_router() increases neigh_nodes refcount if found. */
109 neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); 109 neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
110 if (!neigh_node) 110 if (!neigh_node)
111 return ret; 111 goto out;
112
113 /* Check if the skb is too large to send in one piece and fragment
114 * it if needed.
115 */
116 if (atomic_read(&bat_priv->fragmentation) &&
117 skb->len > neigh_node->if_incoming->net_dev->mtu) {
118 /* Fragment and send packet. */
119 if (batadv_frag_send_packet(skb, orig_node, neigh_node))
120 ret = NET_XMIT_SUCCESS;
121
122 goto out;
123 }
112 124
113 /* try to network code the packet, if it is received on an interface 125 /* try to network code the packet, if it is received on an interface
114 * (i.e. being forwarded). If the packet originates from this node or if 126 * (i.e. being forwarded). If the packet originates from this node or if
@@ -122,8 +134,170 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
122 ret = NET_XMIT_SUCCESS; 134 ret = NET_XMIT_SUCCESS;
123 } 135 }
124 136
125 batadv_neigh_node_free_ref(neigh_node); 137out:
138 if (neigh_node)
139 batadv_neigh_node_free_ref(neigh_node);
140
141 return ret;
142}
126 143
144/**
145 * batadv_send_skb_push_fill_unicast - extend the buffer and initialize the
146 * common fields for unicast packets
147 * @skb: the skb carrying the unicast header to initialize
148 * @hdr_size: amount of bytes to push at the beginning of the skb
149 * @orig_node: the destination node
150 *
151 * Returns false if the buffer extension was not possible or true otherwise.
152 */
153static bool
154batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
155 struct batadv_orig_node *orig_node)
156{
157 struct batadv_unicast_packet *unicast_packet;
158 uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
159
160 if (batadv_skb_head_push(skb, hdr_size) < 0)
161 return false;
162
163 unicast_packet = (struct batadv_unicast_packet *)skb->data;
164 unicast_packet->header.version = BATADV_COMPAT_VERSION;
165 /* batman packet type: unicast */
166 unicast_packet->header.packet_type = BATADV_UNICAST;
167 /* set unicast ttl */
168 unicast_packet->header.ttl = BATADV_TTL;
169 /* copy the destination for faster routing */
170 memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
171 /* set the destination tt version number */
172 unicast_packet->ttvn = ttvn;
173
174 return true;
175}
176
177/**
178 * batadv_send_skb_prepare_unicast - encapsulate an skb with a unicast header
179 * @skb: the skb containing the payload to encapsulate
180 * @orig_node: the destination node
181 *
182 * Returns false if the payload could not be encapsulated or true otherwise.
183 */
184static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb,
185 struct batadv_orig_node *orig_node)
186{
187 size_t uni_size = sizeof(struct batadv_unicast_packet);
188
189 return batadv_send_skb_push_fill_unicast(skb, uni_size, orig_node);
190}
191
192/**
193 * batadv_send_skb_prepare_unicast_4addr - encapsulate an skb with a
194 * unicast 4addr header
195 * @bat_priv: the bat priv with all the soft interface information
196 * @skb: the skb containing the payload to encapsulate
197 * @orig_node: the destination node
198 * @packet_subtype: the unicast 4addr packet subtype to use
199 *
200 * Returns false if the payload could not be encapsulated or true otherwise.
201 */
202bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
203 struct sk_buff *skb,
204 struct batadv_orig_node *orig,
205 int packet_subtype)
206{
207 struct batadv_hard_iface *primary_if;
208 struct batadv_unicast_4addr_packet *uc_4addr_packet;
209 bool ret = false;
210
211 primary_if = batadv_primary_if_get_selected(bat_priv);
212 if (!primary_if)
213 goto out;
214
215 /* Pull the header space and fill the unicast_packet substructure.
216 * We can do that because the first member of the uc_4addr_packet
217 * is of type struct unicast_packet
218 */
219 if (!batadv_send_skb_push_fill_unicast(skb, sizeof(*uc_4addr_packet),
220 orig))
221 goto out;
222
223 uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
224 uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
225 memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
226 uc_4addr_packet->subtype = packet_subtype;
227 uc_4addr_packet->reserved = 0;
228
229 ret = true;
230out:
231 if (primary_if)
232 batadv_hardif_free_ref(primary_if);
233 return ret;
234}
235
236/**
237 * batadv_send_generic_unicast_skb - send an skb as unicast
238 * @bat_priv: the bat priv with all the soft interface information
239 * @skb: payload to send
240 * @packet_type: the batman unicast packet type to use
241 * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
242 * 4addr packets)
243 *
244 * Returns 1 in case of error or 0 otherwise.
245 */
246int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
247 struct sk_buff *skb, int packet_type,
248 int packet_subtype)
249{
250 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
251 struct batadv_unicast_packet *unicast_packet;
252 struct batadv_orig_node *orig_node;
253 int ret = NET_RX_DROP;
254
255 /* get routing information */
256 if (is_multicast_ether_addr(ethhdr->h_dest))
257 orig_node = batadv_gw_get_selected_orig(bat_priv);
258 else
259 /* check for tt host - increases orig_node refcount.
260 * returns NULL in case of AP isolation
261 */
262 orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
263 ethhdr->h_dest);
264
265 if (!orig_node)
266 goto out;
267
268 switch (packet_type) {
269 case BATADV_UNICAST:
270 batadv_send_skb_prepare_unicast(skb, orig_node);
271 break;
272 case BATADV_UNICAST_4ADDR:
273 batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, orig_node,
274 packet_subtype);
275 break;
276 default:
277 /* this function supports UNICAST and UNICAST_4ADDR only. It
278 * should never be invoked with any other packet type
279 */
280 goto out;
281 }
282
283 unicast_packet = (struct batadv_unicast_packet *)skb->data;
284
285 /* inform the destination node that we are still missing a correct route
286 * for this client. The destination will receive this packet and will
287 * try to reroute it because the ttvn contained in the header is less
288 * than the current one
289 */
290 if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest))
291 unicast_packet->ttvn = unicast_packet->ttvn - 1;
292
293 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
294 ret = 0;
295
296out:
297 if (orig_node)
298 batadv_orig_node_free_ref(orig_node);
299 if (ret == NET_RX_DROP)
300 kfree_skb(skb);
127 return ret; 301 return ret;
128} 302}
129 303
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index e7b17880fca4..ad63184a4dd9 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -34,5 +34,45 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work);
34void 34void
35batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, 35batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
36 const struct batadv_hard_iface *hard_iface); 36 const struct batadv_hard_iface *hard_iface);
37bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
38 struct sk_buff *skb,
39 struct batadv_orig_node *orig_node,
40 int packet_subtype);
41int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
42 struct sk_buff *skb, int packet_type,
43 int packet_subtype);
44
45
46/**
47 * batadv_send_unicast_skb - send the skb encapsulated in a unicast packet
48 * @bat_priv: the bat priv with all the soft interface information
49 * @skb: the payload to send
50 *
51 * Returns 1 in case of error or 0 otherwise.
52 */
53static inline int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
54 struct sk_buff *skb)
55{
56 return batadv_send_skb_generic_unicast(bat_priv, skb, BATADV_UNICAST,
57 0);
58}
59
60/**
61 * batadv_send_4addr_unicast_skb - send the skb encapsulated in a unicast 4addr
62 * packet
63 * @bat_priv: the bat priv with all the soft interface information
64 * @skb: the payload to send
65 * @packet_subtype: the unicast 4addr packet subtype to use
66 *
67 * Returns 1 in case of error or 0 otherwise.
68 */
69static inline int batadv_send_skb_unicast_4addr(struct batadv_priv *bat_priv,
70 struct sk_buff *skb,
71 int packet_subtype)
72{
73 return batadv_send_skb_generic_unicast(bat_priv, skb,
74 BATADV_UNICAST_4ADDR,
75 packet_subtype);
76}
37 77
38#endif /* _NET_BATMAN_ADV_SEND_H_ */ 78#endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 25e6004e8e01..e8a2bd699d40 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -34,8 +34,6 @@
34#include <linux/ethtool.h> 34#include <linux/ethtool.h>
35#include <linux/etherdevice.h> 35#include <linux/etherdevice.h>
36#include <linux/if_vlan.h> 36#include <linux/if_vlan.h>
37#include <linux/if_ether.h>
38#include "unicast.h"
39#include "bridge_loop_avoidance.h" 37#include "bridge_loop_avoidance.h"
40#include "network-coding.h" 38#include "network-coding.h"
41 39
@@ -139,6 +137,18 @@ static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu)
139 return 0; 137 return 0;
140} 138}
141 139
140/**
141 * batadv_interface_set_rx_mode - set the rx mode of a device
142 * @dev: registered network device to modify
143 *
144 * We do not actually need to set any rx filters for the virtual batman
145 * soft interface. However a dummy handler enables a user to set static
146 * multicast listeners for instance.
147 */
148static void batadv_interface_set_rx_mode(struct net_device *dev)
149{
150}
151
142static int batadv_interface_tx(struct sk_buff *skb, 152static int batadv_interface_tx(struct sk_buff *skb,
143 struct net_device *soft_iface) 153 struct net_device *soft_iface)
144{ 154{
@@ -147,7 +157,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
147 struct batadv_hard_iface *primary_if = NULL; 157 struct batadv_hard_iface *primary_if = NULL;
148 struct batadv_bcast_packet *bcast_packet; 158 struct batadv_bcast_packet *bcast_packet;
149 struct vlan_ethhdr *vhdr; 159 struct vlan_ethhdr *vhdr;
150 __be16 ethertype = __constant_htons(ETH_P_BATMAN); 160 __be16 ethertype = htons(ETH_P_BATMAN);
151 static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 161 static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
152 0x00, 0x00}; 162 0x00, 0x00};
153 static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, 163 static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
@@ -286,7 +296,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
286 296
287 batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb); 297 batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
288 298
289 ret = batadv_unicast_send_skb(bat_priv, skb); 299 ret = batadv_send_skb_unicast(bat_priv, skb);
290 if (ret != 0) 300 if (ret != 0)
291 goto dropped_freed; 301 goto dropped_freed;
292 } 302 }
@@ -314,7 +324,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
314 struct vlan_ethhdr *vhdr; 324 struct vlan_ethhdr *vhdr;
315 struct batadv_header *batadv_header = (struct batadv_header *)skb->data; 325 struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
316 unsigned short vid __maybe_unused = BATADV_NO_FLAGS; 326 unsigned short vid __maybe_unused = BATADV_NO_FLAGS;
317 __be16 ethertype = __constant_htons(ETH_P_BATMAN); 327 __be16 ethertype = htons(ETH_P_BATMAN);
318 bool is_bcast; 328 bool is_bcast;
319 329
320 is_bcast = (batadv_header->packet_type == BATADV_BCAST); 330 is_bcast = (batadv_header->packet_type == BATADV_BCAST);
@@ -444,6 +454,7 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
444static int batadv_softif_init_late(struct net_device *dev) 454static int batadv_softif_init_late(struct net_device *dev)
445{ 455{
446 struct batadv_priv *bat_priv; 456 struct batadv_priv *bat_priv;
457 uint32_t random_seqno;
447 int ret; 458 int ret;
448 size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM; 459 size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
449 460
@@ -493,6 +504,10 @@ static int batadv_softif_init_late(struct net_device *dev)
493 bat_priv->tt.last_changeset = NULL; 504 bat_priv->tt.last_changeset = NULL;
494 bat_priv->tt.last_changeset_len = 0; 505 bat_priv->tt.last_changeset_len = 0;
495 506
507 /* randomize initial seqno to avoid collision */
508 get_random_bytes(&random_seqno, sizeof(random_seqno));
509 atomic_set(&bat_priv->frag_seqno, random_seqno);
510
496 bat_priv->primary_if = NULL; 511 bat_priv->primary_if = NULL;
497 bat_priv->num_ifaces = 0; 512 bat_priv->num_ifaces = 0;
498 513
@@ -580,6 +595,7 @@ static const struct net_device_ops batadv_netdev_ops = {
580 .ndo_get_stats = batadv_interface_stats, 595 .ndo_get_stats = batadv_interface_stats,
581 .ndo_set_mac_address = batadv_interface_set_mac_addr, 596 .ndo_set_mac_address = batadv_interface_set_mac_addr,
582 .ndo_change_mtu = batadv_interface_change_mtu, 597 .ndo_change_mtu = batadv_interface_change_mtu,
598 .ndo_set_rx_mode = batadv_interface_set_rx_mode,
583 .ndo_start_xmit = batadv_interface_tx, 599 .ndo_start_xmit = batadv_interface_tx,
584 .ndo_validate_addr = eth_validate_addr, 600 .ndo_validate_addr = eth_validate_addr,
585 .ndo_add_slave = batadv_softif_slave_add, 601 .ndo_add_slave = batadv_softif_slave_add,
@@ -623,7 +639,7 @@ static void batadv_softif_init_early(struct net_device *dev)
623 */ 639 */
624 dev->mtu = ETH_DATA_LEN; 640 dev->mtu = ETH_DATA_LEN;
625 /* reserve more space in the skbuff for our header */ 641 /* reserve more space in the skbuff for our header */
626 dev->hard_header_len = BATADV_HEADER_LEN; 642 dev->hard_header_len = batadv_max_header_len();
627 643
628 /* generate random address */ 644 /* generate random address */
629 eth_hw_addr_random(dev); 645 eth_hw_addr_random(dev);
@@ -760,6 +776,12 @@ static const struct {
760 { "mgmt_tx_bytes" }, 776 { "mgmt_tx_bytes" },
761 { "mgmt_rx" }, 777 { "mgmt_rx" },
762 { "mgmt_rx_bytes" }, 778 { "mgmt_rx_bytes" },
779 { "frag_tx" },
780 { "frag_tx_bytes" },
781 { "frag_rx" },
782 { "frag_rx_bytes" },
783 { "frag_fwd" },
784 { "frag_fwd_bytes" },
763 { "tt_request_tx" }, 785 { "tt_request_tx" },
764 { "tt_request_rx" }, 786 { "tt_request_rx" },
765 { "tt_response_tx" }, 787 { "tt_response_tx" },
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index c7416947a4e0..b521afb186d4 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -117,25 +117,17 @@ batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
117 kfree_rcu(tt_local_entry, common.rcu); 117 kfree_rcu(tt_local_entry, common.rcu);
118} 118}
119 119
120static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu) 120/**
121{ 121 * batadv_tt_global_entry_free_ref - decrement the refcounter for a
122 struct batadv_tt_common_entry *tt_common_entry; 122 * tt_global_entry and possibly free it
123 struct batadv_tt_global_entry *tt_global_entry; 123 * @tt_global_entry: the object to free
124 124 */
125 tt_common_entry = container_of(rcu, struct batadv_tt_common_entry, rcu);
126 tt_global_entry = container_of(tt_common_entry,
127 struct batadv_tt_global_entry, common);
128
129 kfree(tt_global_entry);
130}
131
132static void 125static void
133batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) 126batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
134{ 127{
135 if (atomic_dec_and_test(&tt_global_entry->common.refcount)) { 128 if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
136 batadv_tt_global_del_orig_list(tt_global_entry); 129 batadv_tt_global_del_orig_list(tt_global_entry);
137 call_rcu(&tt_global_entry->common.rcu, 130 kfree_rcu(tt_global_entry, common.rcu);
138 batadv_tt_global_entry_free_rcu);
139 } 131 }
140} 132}
141 133
@@ -240,6 +232,17 @@ static int batadv_tt_len(int changes_num)
240 return changes_num * sizeof(struct batadv_tvlv_tt_change); 232 return changes_num * sizeof(struct batadv_tvlv_tt_change);
241} 233}
242 234
235/**
236 * batadv_tt_entries - compute the number of entries fitting in tt_len bytes
237 * @tt_len: available space
238 *
239 * Returns the number of entries.
240 */
241static uint16_t batadv_tt_entries(uint16_t tt_len)
242{
243 return tt_len / batadv_tt_len(1);
244}
245
243static int batadv_tt_local_init(struct batadv_priv *bat_priv) 246static int batadv_tt_local_init(struct batadv_priv *bat_priv)
244{ 247{
245 if (bat_priv->tt.local_hash) 248 if (bat_priv->tt.local_hash)
@@ -414,7 +417,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
414 if (tt_diff_len == 0) 417 if (tt_diff_len == 0)
415 goto container_register; 418 goto container_register;
416 419
417 tt_diff_entries_num = tt_diff_len / batadv_tt_len(1); 420 tt_diff_entries_num = batadv_tt_entries(tt_diff_len);
418 421
419 spin_lock_bh(&bat_priv->tt.changes_list_lock); 422 spin_lock_bh(&bat_priv->tt.changes_list_lock);
420 atomic_set(&bat_priv->tt.local_changes, 0); 423 atomic_set(&bat_priv->tt.local_changes, 0);
@@ -805,15 +808,17 @@ out:
805 * If a TT local entry exists for this non-mesh client remove it. 808 * If a TT local entry exists for this non-mesh client remove it.
806 * 809 *
807 * The caller must hold orig_node refcount. 810 * The caller must hold orig_node refcount.
811 *
812 * Return true if the new entry has been added, false otherwise
808 */ 813 */
809int batadv_tt_global_add(struct batadv_priv *bat_priv, 814static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
810 struct batadv_orig_node *orig_node, 815 struct batadv_orig_node *orig_node,
811 const unsigned char *tt_addr, uint16_t flags, 816 const unsigned char *tt_addr, uint16_t flags,
812 uint8_t ttvn) 817 uint8_t ttvn)
813{ 818{
814 struct batadv_tt_global_entry *tt_global_entry; 819 struct batadv_tt_global_entry *tt_global_entry;
815 struct batadv_tt_local_entry *tt_local_entry; 820 struct batadv_tt_local_entry *tt_local_entry;
816 int ret = 0; 821 bool ret = false;
817 int hash_added; 822 int hash_added;
818 struct batadv_tt_common_entry *common; 823 struct batadv_tt_common_entry *common;
819 uint16_t local_flags; 824 uint16_t local_flags;
@@ -914,7 +919,7 @@ add_orig_entry:
914 batadv_dbg(BATADV_DBG_TT, bat_priv, 919 batadv_dbg(BATADV_DBG_TT, bat_priv,
915 "Creating new global tt entry: %pM (via %pM)\n", 920 "Creating new global tt entry: %pM (via %pM)\n",
916 common->addr, orig_node->orig); 921 common->addr, orig_node->orig);
917 ret = 1; 922 ret = true;
918 923
919out_remove: 924out_remove:
920 925
@@ -1491,11 +1496,9 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
1491 1496
1492static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, 1497static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
1493 struct batadv_orig_node *orig_node, 1498 struct batadv_orig_node *orig_node,
1494 const unsigned char *tt_buff, 1499 const void *tt_buff,
1495 uint16_t tt_num_changes) 1500 uint16_t tt_buff_len)
1496{ 1501{
1497 uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
1498
1499 /* Replace the old buffer only if I received something in the 1502 /* Replace the old buffer only if I received something in the
1500 * last OGM (the OGM could carry no changes) 1503 * last OGM (the OGM could carry no changes)
1501 */ 1504 */
@@ -1622,7 +1625,7 @@ batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1622 tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change); 1625 tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
1623 } 1626 }
1624 1627
1625 tt_tot = tt_len / sizeof(struct batadv_tvlv_tt_change); 1628 tt_tot = batadv_tt_entries(tt_len);
1626 1629
1627 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 1630 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1628 GFP_ATOMIC); 1631 GFP_ATOMIC);
@@ -2032,8 +2035,8 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
2032 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, 2035 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
2033 tt_num_changes, ttvn); 2036 tt_num_changes, ttvn);
2034 2037
2035 batadv_tt_save_orig_buffer(bat_priv, orig_node, 2038 batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
2036 (unsigned char *)tt_change, tt_num_changes); 2039 batadv_tt_len(tt_num_changes));
2037 atomic_set(&orig_node->last_ttvn, ttvn); 2040 atomic_set(&orig_node->last_ttvn, ttvn);
2038} 2041}
2039 2042
@@ -2573,7 +2576,7 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2573 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 2576 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2574 tvlv_value_len -= sizeof(*tt_data); 2577 tvlv_value_len -= sizeof(*tt_data);
2575 2578
2576 num_entries = tvlv_value_len / batadv_tt_len(1); 2579 num_entries = batadv_tt_entries(tvlv_value_len);
2577 2580
2578 batadv_tt_update_orig(bat_priv, orig, 2581 batadv_tt_update_orig(bat_priv, orig,
2579 (unsigned char *)(tt_data + 1), 2582 (unsigned char *)(tt_data + 1),
@@ -2608,7 +2611,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2608 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 2611 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2609 tvlv_value_len -= sizeof(*tt_data); 2612 tvlv_value_len -= sizeof(*tt_data);
2610 2613
2611 num_entries = tvlv_value_len / batadv_tt_len(1); 2614 num_entries = batadv_tt_entries(tvlv_value_len);
2612 2615
2613 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) { 2616 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
2614 case BATADV_TT_REQUEST: 2617 case BATADV_TT_REQUEST:
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index b4b6dea4e2be..015d8b9e63b9 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -27,13 +27,6 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
27 const uint8_t *addr, const char *message, 27 const uint8_t *addr, const char *message,
28 bool roaming); 28 bool roaming);
29int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); 29int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
30void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
31 struct batadv_orig_node *orig_node,
32 const unsigned char *tt_buff, int tt_buff_len);
33int batadv_tt_global_add(struct batadv_priv *bat_priv,
34 struct batadv_orig_node *orig_node,
35 const unsigned char *addr, uint16_t flags,
36 uint8_t ttvn);
37int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); 30int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
38void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, 31void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
39 struct batadv_orig_node *orig_node, 32 struct batadv_orig_node *orig_node,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 8fbd89d167cd..5cbb0d09a9b5 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -24,13 +24,6 @@
24#include "bitarray.h" 24#include "bitarray.h"
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26 26
27/**
28 * Maximum overhead for the encapsulation for a payload packet
29 */
30#define BATADV_HEADER_LEN \
31 (ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
32 sizeof(struct batadv_bcast_packet)))
33
34#ifdef CONFIG_BATMAN_ADV_DAT 27#ifdef CONFIG_BATMAN_ADV_DAT
35 28
36/* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed, 29/* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed,
@@ -60,7 +53,6 @@ struct batadv_hard_iface_bat_iv {
60 * @if_num: identificator of the interface 53 * @if_num: identificator of the interface
61 * @if_status: status of the interface for batman-adv 54 * @if_status: status of the interface for batman-adv
62 * @net_dev: pointer to the net_device 55 * @net_dev: pointer to the net_device
63 * @frag_seqno: last fragment sequence number sent by this interface
64 * @num_bcasts: number of payload re-broadcasts on this interface (ARQ) 56 * @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
65 * @hardif_obj: kobject of the per interface sysfs "mesh" directory 57 * @hardif_obj: kobject of the per interface sysfs "mesh" directory
66 * @refcount: number of contexts the object is used 58 * @refcount: number of contexts the object is used
@@ -76,7 +68,6 @@ struct batadv_hard_iface {
76 int16_t if_num; 68 int16_t if_num;
77 char if_status; 69 char if_status;
78 struct net_device *net_dev; 70 struct net_device *net_dev;
79 atomic_t frag_seqno;
80 uint8_t num_bcasts; 71 uint8_t num_bcasts;
81 struct kobject *hardif_obj; 72 struct kobject *hardif_obj;
82 atomic_t refcount; 73 atomic_t refcount;
@@ -88,6 +79,34 @@ struct batadv_hard_iface {
88}; 79};
89 80
90/** 81/**
82 * struct batadv_frag_table_entry - head in the fragment buffer table
83 * @head: head of list with fragments
84 * @lock: lock to protect the list of fragments
85 * @timestamp: time (jiffie) of last received fragment
86 * @seqno: sequence number of the fragments in the list
87 * @size: accumulated size of packets in list
88 */
89struct batadv_frag_table_entry {
90 struct hlist_head head;
91 spinlock_t lock; /* protects head */
92 unsigned long timestamp;
93 uint16_t seqno;
94 uint16_t size;
95};
96
97/**
98 * struct batadv_frag_list_entry - entry in a list of fragments
99 * @list: list node information
100 * @skb: fragment
101 * @no: fragment number in the set
102 */
103struct batadv_frag_list_entry {
104 struct hlist_node list;
105 struct sk_buff *skb;
106 uint8_t no;
107};
108
109/**
91 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh 110 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh
92 * @orig: originator ethernet address 111 * @orig: originator ethernet address
93 * @primary_addr: hosts primary interface address 112 * @primary_addr: hosts primary interface address
@@ -116,9 +135,6 @@ struct batadv_hard_iface {
116 * last_bcast_seqno) 135 * last_bcast_seqno)
117 * @last_bcast_seqno: last broadcast sequence number received by this host 136 * @last_bcast_seqno: last broadcast sequence number received by this host
118 * @neigh_list: list of potential next hop neighbor towards this orig node 137 * @neigh_list: list of potential next hop neighbor towards this orig node
119 * @frag_list: fragmentation buffer list for fragment re-assembly
120 * @last_frag_packet: time when last fragmented packet from this node was
121 * received
122 * @neigh_list_lock: lock protecting neigh_list, router and bonding_list 138 * @neigh_list_lock: lock protecting neigh_list, router and bonding_list
123 * @hash_entry: hlist node for batadv_priv::orig_hash 139 * @hash_entry: hlist node for batadv_priv::orig_hash
124 * @bat_priv: pointer to soft_iface this orig node belongs to 140 * @bat_priv: pointer to soft_iface this orig node belongs to
@@ -133,6 +149,7 @@ struct batadv_hard_iface {
133 * @out_coding_list: list of nodes that can hear this orig 149 * @out_coding_list: list of nodes that can hear this orig
134 * @in_coding_list_lock: protects in_coding_list 150 * @in_coding_list_lock: protects in_coding_list
135 * @out_coding_list_lock: protects out_coding_list 151 * @out_coding_list_lock: protects out_coding_list
152 * @fragments: array with heads for fragment chains
136 */ 153 */
137struct batadv_orig_node { 154struct batadv_orig_node {
138 uint8_t orig[ETH_ALEN]; 155 uint8_t orig[ETH_ALEN];
@@ -159,8 +176,6 @@ struct batadv_orig_node {
159 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 176 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
160 uint32_t last_bcast_seqno; 177 uint32_t last_bcast_seqno;
161 struct hlist_head neigh_list; 178 struct hlist_head neigh_list;
162 struct list_head frag_list;
163 unsigned long last_frag_packet;
164 /* neigh_list_lock protects: neigh_list, router & bonding_list */ 179 /* neigh_list_lock protects: neigh_list, router & bonding_list */
165 spinlock_t neigh_list_lock; 180 spinlock_t neigh_list_lock;
166 struct hlist_node hash_entry; 181 struct hlist_node hash_entry;
@@ -181,6 +196,7 @@ struct batadv_orig_node {
181 spinlock_t in_coding_list_lock; /* Protects in_coding_list */ 196 spinlock_t in_coding_list_lock; /* Protects in_coding_list */
182 spinlock_t out_coding_list_lock; /* Protects out_coding_list */ 197 spinlock_t out_coding_list_lock; /* Protects out_coding_list */
183#endif 198#endif
199 struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT];
184}; 200};
185 201
186/** 202/**
@@ -277,6 +293,12 @@ struct batadv_bcast_duplist_entry {
277 * @BATADV_CNT_MGMT_TX_BYTES: transmitted routing protocol traffic bytes counter 293 * @BATADV_CNT_MGMT_TX_BYTES: transmitted routing protocol traffic bytes counter
278 * @BATADV_CNT_MGMT_RX: received routing protocol traffic packet counter 294 * @BATADV_CNT_MGMT_RX: received routing protocol traffic packet counter
279 * @BATADV_CNT_MGMT_RX_BYTES: received routing protocol traffic bytes counter 295 * @BATADV_CNT_MGMT_RX_BYTES: received routing protocol traffic bytes counter
296 * @BATADV_CNT_FRAG_TX: transmitted fragment traffic packet counter
297 * @BATADV_CNT_FRAG_TX_BYTES: transmitted fragment traffic bytes counter
298 * @BATADV_CNT_FRAG_RX: received fragment traffic packet counter
299 * @BATADV_CNT_FRAG_RX_BYTES: received fragment traffic bytes counter
300 * @BATADV_CNT_FRAG_FWD: forwarded fragment traffic packet counter
301 * @BATADV_CNT_FRAG_FWD_BYTES: forwarded fragment traffic bytes counter
280 * @BATADV_CNT_TT_REQUEST_TX: transmitted tt req traffic packet counter 302 * @BATADV_CNT_TT_REQUEST_TX: transmitted tt req traffic packet counter
281 * @BATADV_CNT_TT_REQUEST_RX: received tt req traffic packet counter 303 * @BATADV_CNT_TT_REQUEST_RX: received tt req traffic packet counter
282 * @BATADV_CNT_TT_RESPONSE_TX: transmitted tt resp traffic packet counter 304 * @BATADV_CNT_TT_RESPONSE_TX: transmitted tt resp traffic packet counter
@@ -314,6 +336,12 @@ enum batadv_counters {
314 BATADV_CNT_MGMT_TX_BYTES, 336 BATADV_CNT_MGMT_TX_BYTES,
315 BATADV_CNT_MGMT_RX, 337 BATADV_CNT_MGMT_RX,
316 BATADV_CNT_MGMT_RX_BYTES, 338 BATADV_CNT_MGMT_RX_BYTES,
339 BATADV_CNT_FRAG_TX,
340 BATADV_CNT_FRAG_TX_BYTES,
341 BATADV_CNT_FRAG_RX,
342 BATADV_CNT_FRAG_RX_BYTES,
343 BATADV_CNT_FRAG_FWD,
344 BATADV_CNT_FRAG_FWD_BYTES,
317 BATADV_CNT_TT_REQUEST_TX, 345 BATADV_CNT_TT_REQUEST_TX,
318 BATADV_CNT_TT_REQUEST_RX, 346 BATADV_CNT_TT_REQUEST_RX,
319 BATADV_CNT_TT_RESPONSE_TX, 347 BATADV_CNT_TT_RESPONSE_TX,
@@ -511,6 +539,7 @@ struct batadv_priv_nc {
511 * @aggregated_ogms: bool indicating whether OGM aggregation is enabled 539 * @aggregated_ogms: bool indicating whether OGM aggregation is enabled
512 * @bonding: bool indicating whether traffic bonding is enabled 540 * @bonding: bool indicating whether traffic bonding is enabled
513 * @fragmentation: bool indicating whether traffic fragmentation is enabled 541 * @fragmentation: bool indicating whether traffic fragmentation is enabled
542 * @frag_seqno: incremental counter to identify chains of egress fragments
514 * @ap_isolation: bool indicating whether ap isolation is enabled 543 * @ap_isolation: bool indicating whether ap isolation is enabled
515 * @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is 544 * @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is
516 * enabled 545 * enabled
@@ -554,6 +583,7 @@ struct batadv_priv {
554 atomic_t aggregated_ogms; 583 atomic_t aggregated_ogms;
555 atomic_t bonding; 584 atomic_t bonding;
556 atomic_t fragmentation; 585 atomic_t fragmentation;
586 atomic_t frag_seqno;
557 atomic_t ap_isolation; 587 atomic_t ap_isolation;
558#ifdef CONFIG_BATMAN_ADV_BLA 588#ifdef CONFIG_BATMAN_ADV_BLA
559 atomic_t bridge_loop_avoidance; 589 atomic_t bridge_loop_avoidance;
@@ -874,18 +904,6 @@ struct batadv_forw_packet {
874}; 904};
875 905
876/** 906/**
877 * struct batadv_frag_packet_list_entry - storage for fragment packet
878 * @list: list node for orig_node::frag_list
879 * @seqno: sequence number of the fragment
880 * @skb: fragment's skb buffer
881 */
882struct batadv_frag_packet_list_entry {
883 struct list_head list;
884 uint16_t seqno;
885 struct sk_buff *skb;
886};
887
888/**
889 * struct batadv_algo_ops - mesh algorithm callbacks 907 * struct batadv_algo_ops - mesh algorithm callbacks
890 * @list: list node for the batadv_algo_list 908 * @list: list node for the batadv_algo_list
891 * @name: name of the algorithm 909 * @name: name of the algorithm
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
deleted file mode 100644
index 48b31d33ce6b..000000000000
--- a/net/batman-adv/unicast.c
+++ /dev/null
@@ -1,491 +0,0 @@
1/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
2 *
3 * Andreas Langer
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#include "main.h"
21#include "unicast.h"
22#include "send.h"
23#include "soft-interface.h"
24#include "gateway_client.h"
25#include "originator.h"
26#include "hash.h"
27#include "translation-table.h"
28#include "routing.h"
29#include "hard-interface.h"
30
31
32static struct sk_buff *
33batadv_frag_merge_packet(struct list_head *head,
34 struct batadv_frag_packet_list_entry *tfp,
35 struct sk_buff *skb)
36{
37 struct batadv_unicast_frag_packet *up;
38 struct sk_buff *tmp_skb;
39 struct batadv_unicast_packet *unicast_packet;
40 int hdr_len = sizeof(*unicast_packet);
41 int uni_diff = sizeof(*up) - hdr_len;
42 uint8_t *packet_pos;
43
44 up = (struct batadv_unicast_frag_packet *)skb->data;
45 /* set skb to the first part and tmp_skb to the second part */
46 if (up->flags & BATADV_UNI_FRAG_HEAD) {
47 tmp_skb = tfp->skb;
48 } else {
49 tmp_skb = skb;
50 skb = tfp->skb;
51 }
52
53 if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0)
54 goto err;
55
56 skb_pull(tmp_skb, sizeof(*up));
57 if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0)
58 goto err;
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 packet_pos = skb_pull(skb, uni_diff);
70 unicast_packet = (struct batadv_unicast_packet *)packet_pos;
71 unicast_packet->header.packet_type = BATADV_UNICAST;
72
73 return skb;
74
75err:
76 /* free buffered skb, skb will be freed later */
77 kfree_skb(tfp->skb);
78 return NULL;
79}
80
81static void batadv_frag_create_entry(struct list_head *head,
82 struct sk_buff *skb)
83{
84 struct batadv_frag_packet_list_entry *tfp;
85 struct batadv_unicast_frag_packet *up;
86
87 up = (struct batadv_unicast_frag_packet *)skb->data;
88
89 /* free and oldest packets stand at the end */
90 tfp = list_entry((head)->prev, typeof(*tfp), list);
91 kfree_skb(tfp->skb);
92
93 tfp->seqno = ntohs(up->seqno);
94 tfp->skb = skb;
95 list_move(&tfp->list, head);
96 return;
97}
98
99static int batadv_frag_create_buffer(struct list_head *head)
100{
101 int i;
102 struct batadv_frag_packet_list_entry *tfp;
103
104 for (i = 0; i < BATADV_FRAG_BUFFER_SIZE; i++) {
105 tfp = kmalloc(sizeof(*tfp), GFP_ATOMIC);
106 if (!tfp) {
107 batadv_frag_list_free(head);
108 return -ENOMEM;
109 }
110 tfp->skb = NULL;
111 tfp->seqno = 0;
112 INIT_LIST_HEAD(&tfp->list);
113 list_add(&tfp->list, head);
114 }
115
116 return 0;
117}
118
119static struct batadv_frag_packet_list_entry *
120batadv_frag_search_packet(struct list_head *head,
121 const struct batadv_unicast_frag_packet *up)
122{
123 struct batadv_frag_packet_list_entry *tfp;
124 struct batadv_unicast_frag_packet *tmp_up = NULL;
125 bool is_head_tmp, is_head;
126 uint16_t search_seqno;
127
128 if (up->flags & BATADV_UNI_FRAG_HEAD)
129 search_seqno = ntohs(up->seqno)+1;
130 else
131 search_seqno = ntohs(up->seqno)-1;
132
133 is_head = up->flags & BATADV_UNI_FRAG_HEAD;
134
135 list_for_each_entry(tfp, head, list) {
136 if (!tfp->skb)
137 continue;
138
139 if (tfp->seqno == ntohs(up->seqno))
140 goto mov_tail;
141
142 tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
143
144 if (tfp->seqno == search_seqno) {
145 is_head_tmp = tmp_up->flags & BATADV_UNI_FRAG_HEAD;
146 if (is_head_tmp != is_head)
147 return tfp;
148 else
149 goto mov_tail;
150 }
151 }
152 return NULL;
153
154mov_tail:
155 list_move_tail(&tfp->list, head);
156 return NULL;
157}
158
159void batadv_frag_list_free(struct list_head *head)
160{
161 struct batadv_frag_packet_list_entry *pf, *tmp_pf;
162
163 if (!list_empty(head)) {
164 list_for_each_entry_safe(pf, tmp_pf, head, list) {
165 kfree_skb(pf->skb);
166 list_del(&pf->list);
167 kfree(pf);
168 }
169 }
170 return;
171}
172
173/* frag_reassemble_skb():
174 * returns NET_RX_DROP if the operation failed - skb is left intact
175 * returns NET_RX_SUCCESS if the fragment was buffered (skb_new will be NULL)
176 * or the skb could be reassembled (skb_new will point to the new packet and
177 * skb was freed)
178 */
179int batadv_frag_reassemble_skb(struct sk_buff *skb,
180 struct batadv_priv *bat_priv,
181 struct sk_buff **new_skb)
182{
183 struct batadv_orig_node *orig_node;
184 struct batadv_frag_packet_list_entry *tmp_frag_entry;
185 int ret = NET_RX_DROP;
186 struct batadv_unicast_frag_packet *unicast_packet;
187
188 unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
189 *new_skb = NULL;
190
191 orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->orig);
192 if (!orig_node)
193 goto out;
194
195 orig_node->last_frag_packet = jiffies;
196
197 if (list_empty(&orig_node->frag_list) &&
198 batadv_frag_create_buffer(&orig_node->frag_list)) {
199 pr_debug("couldn't create frag buffer\n");
200 goto out;
201 }
202
203 tmp_frag_entry = batadv_frag_search_packet(&orig_node->frag_list,
204 unicast_packet);
205
206 if (!tmp_frag_entry) {
207 batadv_frag_create_entry(&orig_node->frag_list, skb);
208 ret = NET_RX_SUCCESS;
209 goto out;
210 }
211
212 *new_skb = batadv_frag_merge_packet(&orig_node->frag_list,
213 tmp_frag_entry, skb);
214 /* if not, merge failed */
215 if (*new_skb)
216 ret = NET_RX_SUCCESS;
217
218out:
219 if (orig_node)
220 batadv_orig_node_free_ref(orig_node);
221 return ret;
222}
223
224int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
225 struct batadv_hard_iface *hard_iface,
226 const uint8_t dstaddr[])
227{
228 struct batadv_unicast_packet tmp_uc, *unicast_packet;
229 struct batadv_hard_iface *primary_if;
230 struct sk_buff *frag_skb;
231 struct batadv_unicast_frag_packet *frag1, *frag2;
232 int uc_hdr_len = sizeof(*unicast_packet);
233 int ucf_hdr_len = sizeof(*frag1);
234 int data_len = skb->len - uc_hdr_len;
235 int large_tail = 0, ret = NET_RX_DROP;
236 uint16_t seqno;
237
238 primary_if = batadv_primary_if_get_selected(bat_priv);
239 if (!primary_if)
240 goto dropped;
241
242 frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
243 if (!frag_skb)
244 goto dropped;
245
246 skb->priority = TC_PRIO_CONTROL;
247 skb_reserve(frag_skb, ucf_hdr_len);
248
249 unicast_packet = (struct batadv_unicast_packet *)skb->data;
250 memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
251 skb_split(skb, frag_skb, data_len / 2 + uc_hdr_len);
252
253 if (batadv_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
254 batadv_skb_head_push(frag_skb, ucf_hdr_len) < 0)
255 goto drop_frag;
256
257 frag1 = (struct batadv_unicast_frag_packet *)skb->data;
258 frag2 = (struct batadv_unicast_frag_packet *)frag_skb->data;
259
260 memcpy(frag1, &tmp_uc, sizeof(tmp_uc));
261
262 frag1->header.ttl--;
263 frag1->header.version = BATADV_COMPAT_VERSION;
264 frag1->header.packet_type = BATADV_UNICAST_FRAG;
265
266 memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
267 memcpy(frag2, frag1, sizeof(*frag2));
268
269 if (data_len & 1)
270 large_tail = BATADV_UNI_FRAG_LARGETAIL;
271
272 frag1->flags = BATADV_UNI_FRAG_HEAD | large_tail;
273 frag2->flags = large_tail;
274
275 seqno = atomic_add_return(2, &hard_iface->frag_seqno);
276 frag1->seqno = htons(seqno - 1);
277 frag2->seqno = htons(seqno);
278
279 batadv_send_skb_packet(skb, hard_iface, dstaddr);
280 batadv_send_skb_packet(frag_skb, hard_iface, dstaddr);
281 ret = NET_RX_SUCCESS;
282 goto out;
283
284drop_frag:
285 kfree_skb(frag_skb);
286dropped:
287 kfree_skb(skb);
288out:
289 if (primary_if)
290 batadv_hardif_free_ref(primary_if);
291 return ret;
292}
293
294/**
295 * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the
296 * common fields for unicast packets
297 * @skb: packet
298 * @hdr_size: amount of bytes to push at the beginning of the skb
299 * @orig_node: the destination node
300 *
301 * Returns false if the buffer extension was not possible or true otherwise
302 */
303static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
304 struct batadv_orig_node *orig_node)
305{
306 struct batadv_unicast_packet *unicast_packet;
307 uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
308
309 if (batadv_skb_head_push(skb, hdr_size) < 0)
310 return false;
311
312 unicast_packet = (struct batadv_unicast_packet *)skb->data;
313 unicast_packet->header.version = BATADV_COMPAT_VERSION;
314 /* batman packet type: unicast */
315 unicast_packet->header.packet_type = BATADV_UNICAST;
316 /* set unicast ttl */
317 unicast_packet->header.ttl = BATADV_TTL;
318 /* copy the destination for faster routing */
319 memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
320 /* set the destination tt version number */
321 unicast_packet->ttvn = ttvn;
322
323 return true;
324}
325
326/**
327 * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header
328 * @skb: the skb containing the payload to encapsulate
329 * @orig_node: the destination node
330 *
331 * Returns false if the payload could not be encapsulated or true otherwise.
332 *
333 * This call might reallocate skb data.
334 */
335static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
336 struct batadv_orig_node *orig_node)
337{
338 size_t uni_size = sizeof(struct batadv_unicast_packet);
339 return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node);
340}
341
342/**
343 * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr
344 * header
345 * @bat_priv: the bat priv with all the soft interface information
346 * @skb: the skb containing the payload to encapsulate
347 * @orig_node: the destination node
348 * @packet_subtype: the batman 4addr packet subtype to use
349 *
350 * Returns false if the payload could not be encapsulated or true otherwise.
351 *
352 * This call might reallocate skb data.
353 */
354bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
355 struct sk_buff *skb,
356 struct batadv_orig_node *orig,
357 int packet_subtype)
358{
359 struct batadv_hard_iface *primary_if;
360 struct batadv_unicast_4addr_packet *unicast_4addr_packet;
361 bool ret = false;
362
363 primary_if = batadv_primary_if_get_selected(bat_priv);
364 if (!primary_if)
365 goto out;
366
367 /* pull the header space and fill the unicast_packet substructure.
368 * We can do that because the first member of the unicast_4addr_packet
369 * is of type struct unicast_packet
370 */
371 if (!batadv_unicast_push_and_fill_skb(skb,
372 sizeof(*unicast_4addr_packet),
373 orig))
374 goto out;
375
376 unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
377 unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
378 memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr,
379 ETH_ALEN);
380 unicast_4addr_packet->subtype = packet_subtype;
381 unicast_4addr_packet->reserved = 0;
382
383 ret = true;
384out:
385 if (primary_if)
386 batadv_hardif_free_ref(primary_if);
387 return ret;
388}
389
390/**
391 * batadv_unicast_generic_send_skb - send an skb as unicast
392 * @bat_priv: the bat priv with all the soft interface information
393 * @skb: payload to send
394 * @packet_type: the batman unicast packet type to use
395 * @packet_subtype: the batman packet subtype. It is ignored if packet_type is
396 * not BATADV_UNICAT_4ADDR
397 *
398 * Returns 1 in case of error or 0 otherwise
399 */
400int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
401 struct sk_buff *skb, int packet_type,
402 int packet_subtype)
403{
404 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
405 struct batadv_unicast_packet *unicast_packet;
406 struct batadv_orig_node *orig_node;
407 struct batadv_neigh_node *neigh_node;
408 int data_len = skb->len;
409 int ret = NET_RX_DROP;
410 unsigned int dev_mtu, header_len;
411
412 /* get routing information */
413 if (is_multicast_ether_addr(ethhdr->h_dest)) {
414 orig_node = batadv_gw_get_selected_orig(bat_priv);
415 if (orig_node)
416 goto find_router;
417 }
418
419 /* check for tt host - increases orig_node refcount.
420 * returns NULL in case of AP isolation
421 */
422 orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
423 ethhdr->h_dest);
424
425find_router:
426 /* find_router():
427 * - if orig_node is NULL it returns NULL
428 * - increases neigh_nodes refcount if found.
429 */
430 neigh_node = batadv_find_router(bat_priv, orig_node, NULL);
431
432 if (!neigh_node)
433 goto out;
434
435 switch (packet_type) {
436 case BATADV_UNICAST:
437 if (!batadv_unicast_prepare_skb(skb, orig_node))
438 goto out;
439
440 header_len = sizeof(struct batadv_unicast_packet);
441 break;
442 case BATADV_UNICAST_4ADDR:
443 if (!batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
444 packet_subtype))
445 goto out;
446
447 header_len = sizeof(struct batadv_unicast_4addr_packet);
448 break;
449 default:
450 /* this function supports UNICAST and UNICAST_4ADDR only. It
451 * should never be invoked with any other packet type
452 */
453 goto out;
454 }
455
456 ethhdr = (struct ethhdr *)(skb->data + header_len);
457 unicast_packet = (struct batadv_unicast_packet *)skb->data;
458
459 /* inform the destination node that we are still missing a correct route
460 * for this client. The destination will receive this packet and will
461 * try to reroute it because the ttvn contained in the header is less
462 * than the current one
463 */
464 if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest))
465 unicast_packet->ttvn = unicast_packet->ttvn - 1;
466
467 dev_mtu = neigh_node->if_incoming->net_dev->mtu;
468 /* fragmentation mechanism only works for UNICAST (now) */
469 if (packet_type == BATADV_UNICAST &&
470 atomic_read(&bat_priv->fragmentation) &&
471 data_len + sizeof(*unicast_packet) > dev_mtu) {
472 /* send frag skb decreases ttl */
473 unicast_packet->header.ttl++;
474 ret = batadv_frag_send_skb(skb, bat_priv,
475 neigh_node->if_incoming,
476 neigh_node->addr);
477 goto out;
478 }
479
480 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
481 ret = 0;
482
483out:
484 if (neigh_node)
485 batadv_neigh_node_free_ref(neigh_node);
486 if (orig_node)
487 batadv_orig_node_free_ref(orig_node);
488 if (ret == NET_RX_DROP)
489 kfree_skb(skb);
490 return ret;
491}
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
deleted file mode 100644
index 429cf8a4a31e..000000000000
--- a/net/batman-adv/unicast.h
+++ /dev/null
@@ -1,92 +0,0 @@
1/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
2 *
3 * Andreas Langer
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#ifndef _NET_BATMAN_ADV_UNICAST_H_
21#define _NET_BATMAN_ADV_UNICAST_H_
22
23#include "packet.h"
24
25#define BATADV_FRAG_TIMEOUT 10000 /* purge frag list entries after time in ms */
26#define BATADV_FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
27
28int batadv_frag_reassemble_skb(struct sk_buff *skb,
29 struct batadv_priv *bat_priv,
30 struct sk_buff **new_skb);
31void batadv_frag_list_free(struct list_head *head);
32int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
33 struct batadv_hard_iface *hard_iface,
34 const uint8_t dstaddr[]);
35bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
36 struct sk_buff *skb,
37 struct batadv_orig_node *orig_node,
38 int packet_subtype);
39int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
40 struct sk_buff *skb, int packet_type,
41 int packet_subtype);
42
43
44/**
45 * batadv_unicast_send_skb - send the skb encapsulated in a unicast packet
46 * @bat_priv: the bat priv with all the soft interface information
47 * @skb: the payload to send
48 */
49static inline int batadv_unicast_send_skb(struct batadv_priv *bat_priv,
50 struct sk_buff *skb)
51{
52 return batadv_unicast_generic_send_skb(bat_priv, skb, BATADV_UNICAST,
53 0);
54}
55
56/**
57 * batadv_unicast_send_skb - send the skb encapsulated in a unicast4addr packet
58 * @bat_priv: the bat priv with all the soft interface information
59 * @skb: the payload to send
60 * @packet_subtype: the batman 4addr packet subtype to use
61 */
62static inline int batadv_unicast_4addr_send_skb(struct batadv_priv *bat_priv,
63 struct sk_buff *skb,
64 int packet_subtype)
65{
66 return batadv_unicast_generic_send_skb(bat_priv, skb,
67 BATADV_UNICAST_4ADDR,
68 packet_subtype);
69}
70
71static inline int batadv_frag_can_reassemble(const struct sk_buff *skb, int mtu)
72{
73 const struct batadv_unicast_frag_packet *unicast_packet;
74 int uneven_correction = 0;
75 unsigned int merged_size;
76
77 unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
78
79 if (unicast_packet->flags & BATADV_UNI_FRAG_LARGETAIL) {
80 if (unicast_packet->flags & BATADV_UNI_FRAG_HEAD)
81 uneven_correction = 1;
82 else
83 uneven_correction = -1;
84 }
85
86 merged_size = (skb->len - sizeof(*unicast_packet)) * 2;
87 merged_size += sizeof(struct batadv_unicast_packet) + uneven_correction;
88
89 return merged_size <= mtu;
90}
91
92#endif /* _NET_BATMAN_ADV_UNICAST_H_ */