diff options
author | David S. Miller <davem@davemloft.net> | 2013-10-17 14:27:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-17 14:27:09 -0400 |
commit | d7a20c86404bb423f843d4fe34cd1d11432892a0 (patch) | |
tree | b194a2f1e2c6cba499f6b92088937c2d9e98d27a | |
parent | ccdbb6e96beca362db876d820ac1e560ff6d9579 (diff) | |
parent | a4deee1ad42d93746562fe7de2149729017e3fd1 (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/Makefile | 2 | ||||
-rw-r--r-- | net/batman-adv/bridge_loop_avoidance.c | 14 | ||||
-rw-r--r-- | net/batman-adv/distributed-arp-table.c | 11 | ||||
-rw-r--r-- | net/batman-adv/fragmentation.c | 491 | ||||
-rw-r--r-- | net/batman-adv/fragmentation.h | 50 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 23 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 22 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 22 | ||||
-rw-r--r-- | net/batman-adv/main.c | 37 | ||||
-rw-r--r-- | net/batman-adv/main.h | 10 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 19 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 79 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 185 | ||||
-rw-r--r-- | net/batman-adv/routing.h | 4 | ||||
-rw-r--r-- | net/batman-adv/send.c | 186 | ||||
-rw-r--r-- | net/batman-adv/send.h | 40 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 34 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 63 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 7 | ||||
-rw-r--r-- | net/batman-adv/types.h | 70 | ||||
-rw-r--r-- | net/batman-adv/unicast.c | 491 | ||||
-rw-r--r-- | net/batman-adv/unicast.h | 92 |
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 | |||
24 | batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o | 24 | batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o |
25 | batman-adv-y += debugfs.o | 25 | batman-adv-y += debugfs.o |
26 | batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o | 26 | batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o |
27 | batman-adv-y += fragmentation.o | ||
27 | batman-adv-y += gateway_client.o | 28 | batman-adv-y += gateway_client.o |
28 | batman-adv-y += gateway_common.o | 29 | batman-adv-y += gateway_common.o |
29 | batman-adv-y += hard-interface.o | 30 | batman-adv-y += hard-interface.o |
@@ -37,4 +38,3 @@ batman-adv-y += send.o | |||
37 | batman-adv-y += soft-interface.o | 38 | batman-adv-y += soft-interface.o |
38 | batman-adv-y += sysfs.o | 39 | batman-adv-y += sysfs.o |
39 | batman-adv-y += translation-table.o | 40 | batman-adv-y += translation-table.o |
40 | batman-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 | ||
34 | static void batadv_dat_purge(struct work_struct *work); | 33 | static 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 | */ | ||
35 | static 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 | */ | ||
52 | void 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 | */ | ||
76 | static 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 | */ | ||
99 | static 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 | */ | ||
127 | static 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 | |||
195 | out: | ||
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 | |||
209 | err_unlock: | ||
210 | spin_unlock_bh(&chain->lock); | ||
211 | |||
212 | err: | ||
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 | */ | ||
229 | static struct sk_buff * | ||
230 | batadv_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 | |||
274 | free: | ||
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 | */ | ||
291 | bool 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 | |||
310 | out: | ||
311 | *skb = skb_out; | ||
312 | ret = true; | ||
313 | out_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 | */ | ||
329 | bool 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 | |||
364 | out: | ||
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 | */ | ||
384 | static 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 | |||
406 | err: | ||
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 | */ | ||
418 | bool 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; | ||
489 | out_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 | |||
23 | void batadv_frag_purge_orig(struct batadv_orig_node *orig, | ||
24 | bool (*check_cb)(struct batadv_frag_table_entry *)); | ||
25 | bool batadv_frag_skb_fwd(struct sk_buff *skb, | ||
26 | struct batadv_hard_iface *recv_if, | ||
27 | struct batadv_orig_node *orig_node_src); | ||
28 | bool batadv_frag_skb_buffer(struct sk_buff **skb, | ||
29 | struct batadv_orig_node *orig_node); | ||
30 | bool 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 | */ | ||
40 | static inline bool | ||
41 | batadv_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 | ||
246 | dst_unreach: | 246 | dst_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); |
249 | free_skb: | 249 | free_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 | */ | ||
264 | int 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 | ||
423 | int | 448 | int |
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); | |||
182 | int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr); | 191 | int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr); |
183 | struct batadv_hard_iface * | 192 | struct batadv_hard_iface * |
184 | batadv_seq_print_text_primary_if_get(struct seq_file *seq); | 193 | batadv_seq_print_text_primary_if_get(struct seq_file *seq); |
194 | int batadv_max_header_len(void); | ||
185 | void batadv_skb_set_priority(struct sk_buff *skb, int offset); | 195 | void batadv_skb_set_priority(struct sk_buff *skb, int offset); |
186 | int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | 196 | int 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 */ |
34 | static struct lock_class_key batadv_orig_hash_lock_class_key; | 34 | static 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 */ | ||
95 | enum 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 | ||
195 | struct 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 | */ | ||
197 | struct 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 | */ | ||
211 | struct 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 | */ |
210 | struct batadv_icmp_packet_rr { | 226 | struct 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 | ||
258 | struct 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 | */ | ||
280 | struct 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 | ||
268 | struct batadv_bcast_packet { | 297 | struct 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 | ||
33 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 33 | static 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 | ||
748 | out: | 716 | out: |
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 | ||
1004 | int 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 | |||
1042 | rx_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 | */ | ||
1030 | int 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 | |||
1070 | out: | ||
1071 | if (orig_node_src) | ||
1072 | batadv_orig_node_free_ref(orig_node_src); | ||
1073 | |||
1074 | return ret; | ||
1075 | } | ||
1076 | |||
1098 | int batadv_recv_bcast_packet(struct sk_buff *skb, | 1077 | int 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); |
31 | int batadv_recv_unicast_packet(struct sk_buff *skb, | 31 | int batadv_recv_unicast_packet(struct sk_buff *skb, |
32 | struct batadv_hard_iface *recv_if); | 32 | struct batadv_hard_iface *recv_if); |
33 | int batadv_recv_ucast_frag_packet(struct sk_buff *skb, | 33 | int batadv_recv_frag_packet(struct sk_buff *skb, |
34 | struct batadv_hard_iface *recv_if); | 34 | struct batadv_hard_iface *iface); |
35 | int batadv_recv_bcast_packet(struct sk_buff *skb, | 35 | int batadv_recv_bcast_packet(struct sk_buff *skb, |
36 | struct batadv_hard_iface *recv_if); | 36 | struct batadv_hard_iface *recv_if); |
37 | int batadv_recv_tt_query(struct sk_buff *skb, | 37 | int 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 | ||
33 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work); | 33 | static 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); | 137 | out: |
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 | */ | ||
153 | static bool | ||
154 | batadv_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 | */ | ||
184 | static 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 | */ | ||
202 | bool 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; | ||
230 | out: | ||
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 | */ | ||
246 | int 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 | |||
296 | out: | ||
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); | |||
34 | void | 34 | void |
35 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | 35 | batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, |
36 | const struct batadv_hard_iface *hard_iface); | 36 | const struct batadv_hard_iface *hard_iface); |
37 | bool 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); | ||
41 | int 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 | */ | ||
53 | static 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 | */ | ||
69 | static 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 | */ | ||
148 | static void batadv_interface_set_rx_mode(struct net_device *dev) | ||
149 | { | ||
150 | } | ||
151 | |||
142 | static int batadv_interface_tx(struct sk_buff *skb, | 152 | static 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) | |||
444 | static int batadv_softif_init_late(struct net_device *dev) | 454 | static 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 | ||
120 | static 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 | |||
132 | static void | 125 | static void |
133 | batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) | 126 | batadv_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 | */ | ||
241 | static uint16_t batadv_tt_entries(uint16_t tt_len) | ||
242 | { | ||
243 | return tt_len / batadv_tt_len(1); | ||
244 | } | ||
245 | |||
243 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) | 246 | static 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 | */ |
809 | int batadv_tt_global_add(struct batadv_priv *bat_priv, | 814 | static 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 | ||
919 | out_remove: | 924 | out_remove: |
920 | 925 | ||
@@ -1491,11 +1496,9 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) | |||
1491 | 1496 | ||
1492 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, | 1497 | static 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); |
29 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); | 29 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); |
30 | void 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); | ||
33 | int 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); | ||
37 | int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); | 30 | int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); |
38 | void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | 31 | void 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 | */ | ||
89 | struct 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 | */ | ||
103 | struct 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 | */ |
137 | struct batadv_orig_node { | 154 | struct 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 | */ | ||
882 | struct 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 | |||
32 | static struct sk_buff * | ||
33 | batadv_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 | |||
75 | err: | ||
76 | /* free buffered skb, skb will be freed later */ | ||
77 | kfree_skb(tfp->skb); | ||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | static 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 | |||
99 | static 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 | |||
119 | static struct batadv_frag_packet_list_entry * | ||
120 | batadv_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 | |||
154 | mov_tail: | ||
155 | list_move_tail(&tfp->list, head); | ||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | void 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 | */ | ||
179 | int 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 | |||
218 | out: | ||
219 | if (orig_node) | ||
220 | batadv_orig_node_free_ref(orig_node); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | int 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 | |||
284 | drop_frag: | ||
285 | kfree_skb(frag_skb); | ||
286 | dropped: | ||
287 | kfree_skb(skb); | ||
288 | out: | ||
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 | */ | ||
303 | static 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 | */ | ||
335 | static 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 | */ | ||
354 | bool 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; | ||
384 | out: | ||
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 | */ | ||
400 | int 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 | |||
425 | find_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 | |||
483 | out: | ||
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 | |||
28 | int batadv_frag_reassemble_skb(struct sk_buff *skb, | ||
29 | struct batadv_priv *bat_priv, | ||
30 | struct sk_buff **new_skb); | ||
31 | void batadv_frag_list_free(struct list_head *head); | ||
32 | int 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[]); | ||
35 | bool 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); | ||
39 | int 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 | */ | ||
49 | static 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 | */ | ||
62 | static 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 | |||
71 | static 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_ */ | ||