Blame view

net/batman-adv/send.c 29.4 KB
ac79cbb96   Sven Eckelmann   batman-adv: updat...
1
  /* Copyright (C) 2007-2017  B.A.T.M.A.N. contributors:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
2
3
4
5
6
7
8
9
10
11
12
13
14
   *
   * Marek Lindner, Simon Wunderlich
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
ebf38fb7a   Antonio Quartulli   batman-adv: remov...
15
   * along with this program; if not, see <http://www.gnu.org/licenses/>.
c6c8fea29   Sven Eckelmann   net: Add batman-a...
16
   */
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
17
  #include "send.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
18
  #include "main.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
19
20
  
  #include <linux/atomic.h>
9b4aec647   Linus Lüssing   batman-adv: fix r...
21
  #include <linux/bug.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
22
  #include <linux/byteorder/generic.h>
f50ca95a6   Antonio Quartulli   batman-adv: retur...
23
  #include <linux/errno.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
24
25
  #include <linux/etherdevice.h>
  #include <linux/fs.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
26
  #include <linux/if.h>
fcafa5e74   Sven Eckelmann   batman-adv: Keep ...
27
  #include <linux/if_ether.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
28
29
  #include <linux/jiffies.h>
  #include <linux/kernel.h>
273534468   Sven Eckelmann   batman-adv: Check...
30
  #include <linux/kref.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
31
32
33
34
35
36
37
38
39
40
  #include <linux/list.h>
  #include <linux/netdevice.h>
  #include <linux/printk.h>
  #include <linux/rculist.h>
  #include <linux/rcupdate.h>
  #include <linux/skbuff.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/stddef.h>
  #include <linux/workqueue.h>
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
41
  #include "distributed-arp-table.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
42
  #include "fragmentation.h"
f097e25db   Martin Hundebøll   batman-adv: Remov...
43
  #include "gateway_client.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
44
  #include "hard-interface.h"
ba412080f   Sven Eckelmann   batman-adv: Conso...
45
  #include "log.h"
612d2b4fe   Martin Hundebøll   batman-adv: netwo...
46
  #include "network-coding.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
47
48
49
50
  #include "originator.h"
  #include "routing.h"
  #include "soft-interface.h"
  #include "translation-table.h"
af5d4f773   Antonio Quartulli   batman-adv: use E...
51

bb079c82e   Sven Eckelmann   batman-adv: Prefi...
52
  static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
53

95d392784   Antonio Quartulli   batman-adv: keep ...
54
55
56
57
58
59
60
61
62
63
64
65
  /**
   * batadv_send_skb_packet - send an already prepared packet
   * @skb: the packet to send
   * @hard_iface: the interface to use to send the broadcast packet
   * @dst_addr: the payload destination
   *
   * Send out an already prepared packet to the given neighbor or broadcast it
   * using the specified interface. Either hard_iface or neigh_node must be not
   * NULL.
   * If neigh_node is NULL, then the packet is broadcasted using hard_iface,
   * otherwise it is sent as unicast to the given neighbor.
   *
7d72d174c   Sven Eckelmann   batman-adv: Remov...
66
67
68
69
70
   * Regardless of the return value, the skb is consumed.
   *
   * Return: A negative errno code is returned on a failure. A success does not
   * guarantee the frame will be transmitted as it may be dropped due
   * to congestion or traffic shaping.
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
71
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
72
73
  int batadv_send_skb_packet(struct sk_buff *skb,
  			   struct batadv_hard_iface *hard_iface,
6b5e971a2   Sven Eckelmann   batman-adv: Repla...
74
  			   const u8 *dst_addr)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
75
  {
95d392784   Antonio Quartulli   batman-adv: keep ...
76
  	struct batadv_priv *bat_priv;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
77
  	struct ethhdr *ethhdr;
7c946062b   Sven Eckelmann   batman-adv: Fix d...
78
  	int ret;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
79

95d392784   Antonio Quartulli   batman-adv: keep ...
80
  	bat_priv = netdev_priv(hard_iface->soft_iface);
e9a4f295e   Sven Eckelmann   batman-adv: Prefi...
81
  	if (hard_iface->if_status != BATADV_IF_ACTIVE)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
82
  		goto send_skb_err;
e6c10f433   Marek Lindner   batman-adv: renam...
83
  	if (unlikely(!hard_iface->net_dev))
c6c8fea29   Sven Eckelmann   net: Add batman-a...
84
  		goto send_skb_err;
e6c10f433   Marek Lindner   batman-adv: renam...
85
  	if (!(hard_iface->net_dev->flags & IFF_UP)) {
679695813   Sven Eckelmann   batman-adv: use s...
86
87
88
  		pr_warn("Interface %s is not up - can't send packet via that interface!
  ",
  			hard_iface->net_dev->name);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
89
90
91
92
  		goto send_skb_err;
  	}
  
  	/* push to the ethernet header. */
04b482a21   Sven Eckelmann   batman-adv: Prefi...
93
  	if (batadv_skb_head_push(skb, ETH_HLEN) < 0)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
94
95
96
  		goto send_skb_err;
  
  	skb_reset_mac_header(skb);
7ed4be952   Antonio Quartulli   batman-adv: use e...
97
  	ethhdr = eth_hdr(skb);
8fdd01530   Antonio Quartulli   batman-adv: prefe...
98
99
  	ether_addr_copy(ethhdr->h_source, hard_iface->net_dev->dev_addr);
  	ether_addr_copy(ethhdr->h_dest, dst_addr);
293e93385   Antonio Quartulli   batman-adv: use h...
100
  	ethhdr->h_proto = htons(ETH_P_BATMAN);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
101
102
  
  	skb_set_network_header(skb, ETH_HLEN);
293e93385   Antonio Quartulli   batman-adv: use h...
103
  	skb->protocol = htons(ETH_P_BATMAN);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
104

e6c10f433   Marek Lindner   batman-adv: renam...
105
  	skb->dev = hard_iface->net_dev;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
106

612d2b4fe   Martin Hundebøll   batman-adv: netwo...
107
108
  	/* Save a clone of the skb to use when decoding coded packets */
  	batadv_nc_skb_store_for_decoding(bat_priv, skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
109
110
  	/* dev_queue_xmit() returns a negative result on error.	 However on
  	 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
111
112
  	 * (which is > 0). This will not be treated as an error.
  	 */
7c946062b   Sven Eckelmann   batman-adv: Fix d...
113
114
  	ret = dev_queue_xmit(skb);
  	return net_xmit_eval(ret);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
115
116
117
118
  send_skb_err:
  	kfree_skb(skb);
  	return NET_XMIT_DROP;
  }
95d392784   Antonio Quartulli   batman-adv: keep ...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  int batadv_send_broadcast_skb(struct sk_buff *skb,
  			      struct batadv_hard_iface *hard_iface)
  {
  	return batadv_send_skb_packet(skb, hard_iface, batadv_broadcast_addr);
  }
  
  int batadv_send_unicast_skb(struct sk_buff *skb,
  			    struct batadv_neigh_node *neigh)
  {
  #ifdef CONFIG_BATMAN_ADV_BATMAN_V
  	struct batadv_hardif_neigh_node *hardif_neigh;
  #endif
  	int ret;
  
  	ret = batadv_send_skb_packet(skb, neigh->if_incoming, neigh->addr);
  
  #ifdef CONFIG_BATMAN_ADV_BATMAN_V
  	hardif_neigh = batadv_hardif_neigh_get(neigh->if_incoming, neigh->addr);
  
  	if ((hardif_neigh) && (ret != NET_XMIT_DROP))
  		hardif_neigh->bat_v.last_unicast_tx = jiffies;
  
  	if (hardif_neigh)
  		batadv_hardif_neigh_put(hardif_neigh);
  #endif
  
  	return ret;
  }
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
147
148
149
150
151
152
153
154
155
156
157
  /**
   * batadv_send_skb_to_orig - Lookup next-hop and transmit skb.
   * @skb: Packet to be transmitted.
   * @orig_node: Final destination of the packet.
   * @recv_if: Interface used when receiving the packet (can be NULL).
   *
   * Looks up the best next-hop towards the passed originator and passes the
   * skb on for preparation of MAC header. If the packet originated from this
   * host, NULL can be passed as recv_if and no interface alternating is
   * attempted.
   *
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
158
159
   * Return: negative errno code on a failure, -EINPROGRESS if the skb is
   * buffered for later transmit or the NET_XMIT status returned by the
f50ca95a6   Antonio Quartulli   batman-adv: retur...
160
   * lower routine if the packet has been passed down.
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
161
   */
e91ecfc64   Martin Hundebøll   batman-adv: Move ...
162
163
164
  int batadv_send_skb_to_orig(struct sk_buff *skb,
  			    struct batadv_orig_node *orig_node,
  			    struct batadv_hard_iface *recv_if)
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
165
166
167
  {
  	struct batadv_priv *bat_priv = orig_node->bat_priv;
  	struct batadv_neigh_node *neigh_node;
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
168
  	int ret;
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
169
170
171
  
  	/* batadv_find_router() increases neigh_nodes refcount if found. */
  	neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
172
173
174
175
  	if (!neigh_node) {
  		ret = -EINVAL;
  		goto free_skb;
  	}
ee75ed888   Martin Hundebøll   batman-adv: Fragm...
176
177
178
179
180
181
182
  
  	/* Check if the skb is too large to send in one piece and fragment
  	 * it if needed.
  	 */
  	if (atomic_read(&bat_priv->fragmentation) &&
  	    skb->len > neigh_node->if_incoming->net_dev->mtu) {
  		/* Fragment and send packet. */
f50ca95a6   Antonio Quartulli   batman-adv: retur...
183
  		ret = batadv_frag_send_packet(skb, orig_node, neigh_node);
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
184
185
  		/* skb was consumed */
  		skb = NULL;
ee75ed888   Martin Hundebøll   batman-adv: Fragm...
186

1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
187
  		goto put_neigh_node;
ee75ed888   Martin Hundebøll   batman-adv: Fragm...
188
  	}
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
189

e91ecfc64   Martin Hundebøll   batman-adv: Move ...
190
191
192
193
  	/* try to network code the packet, if it is received on an interface
  	 * (i.e. being forwarded). If the packet originates from this node or if
  	 * network coding fails, then send the packet as usual.
  	 */
f50ca95a6   Antonio Quartulli   batman-adv: retur...
194
  	if (recv_if && batadv_nc_skb_forward(skb, neigh_node))
99860208b   Florian Westphal   sched: remove NET...
195
  		ret = -EINPROGRESS;
f50ca95a6   Antonio Quartulli   batman-adv: retur...
196
197
  	else
  		ret = batadv_send_unicast_skb(skb, neigh_node);
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
198

1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
199
200
201
202
203
204
205
  	/* skb was consumed */
  	skb = NULL;
  
  put_neigh_node:
  	batadv_neigh_node_put(neigh_node);
  free_skb:
  	kfree_skb(skb);
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
206

e91ecfc64   Martin Hundebøll   batman-adv: Move ...
207
  	return ret;
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
208
  }
f097e25db   Martin Hundebøll   batman-adv: Remov...
209
210
211
212
213
214
215
  /**
   * batadv_send_skb_push_fill_unicast - extend the buffer and initialize the
   *  common fields for unicast packets
   * @skb: the skb carrying the unicast header to initialize
   * @hdr_size: amount of bytes to push at the beginning of the skb
   * @orig_node: the destination node
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
216
   * Return: false if the buffer extension was not possible or true otherwise.
f097e25db   Martin Hundebøll   batman-adv: Remov...
217
218
219
220
221
222
   */
  static bool
  batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
  				  struct batadv_orig_node *orig_node)
  {
  	struct batadv_unicast_packet *unicast_packet;
6b5e971a2   Sven Eckelmann   batman-adv: Repla...
223
  	u8 ttvn = (u8)atomic_read(&orig_node->last_ttvn);
f097e25db   Martin Hundebøll   batman-adv: Remov...
224
225
226
227
228
  
  	if (batadv_skb_head_push(skb, hdr_size) < 0)
  		return false;
  
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
a40d9b075   Simon Wunderlich   batman-adv: fix h...
229
  	unicast_packet->version = BATADV_COMPAT_VERSION;
f097e25db   Martin Hundebøll   batman-adv: Remov...
230
  	/* batman packet type: unicast */
a40d9b075   Simon Wunderlich   batman-adv: fix h...
231
  	unicast_packet->packet_type = BATADV_UNICAST;
f097e25db   Martin Hundebøll   batman-adv: Remov...
232
  	/* set unicast ttl */
a40d9b075   Simon Wunderlich   batman-adv: fix h...
233
  	unicast_packet->ttl = BATADV_TTL;
f097e25db   Martin Hundebøll   batman-adv: Remov...
234
  	/* copy the destination for faster routing */
8fdd01530   Antonio Quartulli   batman-adv: prefe...
235
  	ether_addr_copy(unicast_packet->dest, orig_node->orig);
f097e25db   Martin Hundebøll   batman-adv: Remov...
236
237
238
239
240
241
242
243
244
245
246
  	/* set the destination tt version number */
  	unicast_packet->ttvn = ttvn;
  
  	return true;
  }
  
  /**
   * batadv_send_skb_prepare_unicast - encapsulate an skb with a unicast header
   * @skb: the skb containing the payload to encapsulate
   * @orig_node: the destination node
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
247
   * Return: false if the payload could not be encapsulated or true otherwise.
f097e25db   Martin Hundebøll   batman-adv: Remov...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
   */
  static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb,
  					    struct batadv_orig_node *orig_node)
  {
  	size_t uni_size = sizeof(struct batadv_unicast_packet);
  
  	return batadv_send_skb_push_fill_unicast(skb, uni_size, orig_node);
  }
  
  /**
   * batadv_send_skb_prepare_unicast_4addr - encapsulate an skb with a
   *  unicast 4addr header
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: the skb containing the payload to encapsulate
e51f0397d   Sven Eckelmann   batman-adv: Fix n...
262
   * @orig: the destination node
f097e25db   Martin Hundebøll   batman-adv: Remov...
263
264
   * @packet_subtype: the unicast 4addr packet subtype to use
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
265
   * Return: false if the payload could not be encapsulated or true otherwise.
f097e25db   Martin Hundebøll   batman-adv: Remov...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
   */
  bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
  					   struct sk_buff *skb,
  					   struct batadv_orig_node *orig,
  					   int packet_subtype)
  {
  	struct batadv_hard_iface *primary_if;
  	struct batadv_unicast_4addr_packet *uc_4addr_packet;
  	bool ret = false;
  
  	primary_if = batadv_primary_if_get_selected(bat_priv);
  	if (!primary_if)
  		goto out;
  
  	/* Pull the header space and fill the unicast_packet substructure.
  	 * We can do that because the first member of the uc_4addr_packet
  	 * is of type struct unicast_packet
  	 */
  	if (!batadv_send_skb_push_fill_unicast(skb, sizeof(*uc_4addr_packet),
  					       orig))
  		goto out;
  
  	uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
a40d9b075   Simon Wunderlich   batman-adv: fix h...
289
  	uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
290
  	ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr);
f097e25db   Martin Hundebøll   batman-adv: Remov...
291
292
293
294
295
296
  	uc_4addr_packet->subtype = packet_subtype;
  	uc_4addr_packet->reserved = 0;
  
  	ret = true;
  out:
  	if (primary_if)
82047ad7f   Sven Eckelmann   batman-adv: Renam...
297
  		batadv_hardif_put(primary_if);
f097e25db   Martin Hundebøll   batman-adv: Remov...
298
299
300
301
  	return ret;
  }
  
  /**
e300d3146   Linus Lüssing   batman-adv: refin...
302
   * batadv_send_skb_unicast - encapsulate and send an skb via unicast
f097e25db   Martin Hundebøll   batman-adv: Remov...
303
304
305
306
307
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: payload to send
   * @packet_type: the batman unicast packet type to use
   * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
   *  4addr packets)
e300d3146   Linus Lüssing   batman-adv: refin...
308
   * @orig_node: the originator to send the packet to
c018ad3de   Antonio Quartulli   batman-adv: add t...
309
   * @vid: the vid to be used to search the translation table
f097e25db   Martin Hundebøll   batman-adv: Remov...
310
   *
e300d3146   Linus Lüssing   batman-adv: refin...
311
312
   * Wrap the given skb into a batman-adv unicast or unicast-4addr header
   * depending on whether BATADV_UNICAST or BATADV_UNICAST_4ADDR was supplied
f19dc7770   Sven Eckelmann   batman-adv: Remov...
313
   * as packet_type. Then send this frame to the given orig_node.
e300d3146   Linus Lüssing   batman-adv: refin...
314
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
315
   * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
f097e25db   Martin Hundebøll   batman-adv: Remov...
316
   */
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
317
318
319
320
321
  int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
  			    struct sk_buff *skb, int packet_type,
  			    int packet_subtype,
  			    struct batadv_orig_node *orig_node,
  			    unsigned short vid)
f097e25db   Martin Hundebøll   batman-adv: Remov...
322
  {
f097e25db   Martin Hundebøll   batman-adv: Remov...
323
  	struct batadv_unicast_packet *unicast_packet;
8ea64e270   Antonio Quartulli   batman-adv: Use c...
324
  	struct ethhdr *ethhdr;
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
325
  	int ret = NET_XMIT_DROP;
f097e25db   Martin Hundebøll   batman-adv: Remov...
326

56a5ca840   Simon Wunderlich   batman-adv: remov...
327
  	if (!orig_node)
f097e25db   Martin Hundebøll   batman-adv: Remov...
328
329
330
331
  		goto out;
  
  	switch (packet_type) {
  	case BATADV_UNICAST:
33faa0454   Antonio Quartulli   batman-adv: check...
332
333
  		if (!batadv_send_skb_prepare_unicast(skb, orig_node))
  			goto out;
f097e25db   Martin Hundebøll   batman-adv: Remov...
334
335
  		break;
  	case BATADV_UNICAST_4ADDR:
33faa0454   Antonio Quartulli   batman-adv: check...
336
337
338
339
  		if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb,
  							   orig_node,
  							   packet_subtype))
  			goto out;
f097e25db   Martin Hundebøll   batman-adv: Remov...
340
341
342
343
344
345
346
  		break;
  	default:
  		/* this function supports UNICAST and UNICAST_4ADDR only. It
  		 * should never be invoked with any other packet type
  		 */
  		goto out;
  	}
927c2ed7e   Linus Lüssing   batman-adv: use v...
347
348
349
350
  	/* skb->data might have been reallocated by
  	 * batadv_send_skb_prepare_unicast{,_4addr}()
  	 */
  	ethhdr = eth_hdr(skb);
f097e25db   Martin Hundebøll   batman-adv: Remov...
351
352
353
354
355
356
357
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
  
  	/* inform the destination node that we are still missing a correct route
  	 * for this client. The destination will receive this packet and will
  	 * try to reroute it because the ttvn contained in the header is less
  	 * than the current one
  	 */
c018ad3de   Antonio Quartulli   batman-adv: add t...
358
  	if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
f097e25db   Martin Hundebøll   batman-adv: Remov...
359
  		unicast_packet->ttvn = unicast_packet->ttvn - 1;
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
360
361
362
  	ret = batadv_send_skb_to_orig(skb, orig_node, NULL);
  	 /* skb was consumed */
  	skb = NULL;
f097e25db   Martin Hundebøll   batman-adv: Remov...
363
364
  
  out:
1ad5bcb2a   Sven Eckelmann   batman-adv: Consu...
365
  	kfree_skb(skb);
f097e25db   Martin Hundebøll   batman-adv: Remov...
366
367
  	return ret;
  }
e300d3146   Linus Lüssing   batman-adv: refin...
368
369
370
371
372
373
374
  /**
   * batadv_send_skb_via_tt_generic - send an skb via TT lookup
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: payload to send
   * @packet_type: the batman unicast packet type to use
   * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
   *  4addr packets)
c5d3a652a   Antonio Quartulli   batman-adv: add k...
375
   * @dst_hint: can be used to override the destination contained in the skb
e300d3146   Linus Lüssing   batman-adv: refin...
376
377
378
379
380
381
382
383
   * @vid: the vid to be used to search the translation table
   *
   * Look up the recipient node for the destination address in the ethernet
   * header via the translation table. Wrap the given skb into a batman-adv
   * unicast or unicast-4addr header depending on whether BATADV_UNICAST or
   * BATADV_UNICAST_4ADDR was supplied as packet_type. Then send this frame
   * to the according destination node.
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
384
   * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
e300d3146   Linus Lüssing   batman-adv: refin...
385
386
387
   */
  int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
  				   struct sk_buff *skb, int packet_type,
6b5e971a2   Sven Eckelmann   batman-adv: Repla...
388
  				   int packet_subtype, u8 *dst_hint,
6c413b1c2   Antonio Quartulli   batman-adv: send ...
389
  				   unsigned short vid)
e300d3146   Linus Lüssing   batman-adv: refin...
390
391
392
  {
  	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
  	struct batadv_orig_node *orig_node;
6b5e971a2   Sven Eckelmann   batman-adv: Repla...
393
  	u8 *src, *dst;
f19dc7770   Sven Eckelmann   batman-adv: Remov...
394
  	int ret;
6c413b1c2   Antonio Quartulli   batman-adv: send ...
395
396
397
398
399
400
401
402
403
404
  
  	src = ethhdr->h_source;
  	dst = ethhdr->h_dest;
  
  	/* if we got an hint! let's send the packet to this client (if any) */
  	if (dst_hint) {
  		src = NULL;
  		dst = dst_hint;
  	}
  	orig_node = batadv_transtable_search(bat_priv, src, dst, vid);
e300d3146   Linus Lüssing   batman-adv: refin...
405

f19dc7770   Sven Eckelmann   batman-adv: Remov...
406
407
408
409
410
411
412
  	ret = batadv_send_skb_unicast(bat_priv, skb, packet_type,
  				      packet_subtype, orig_node, vid);
  
  	if (orig_node)
  		batadv_orig_node_put(orig_node);
  
  	return ret;
e300d3146   Linus Lüssing   batman-adv: refin...
413
414
415
416
417
418
419
420
421
422
423
  }
  
  /**
   * batadv_send_skb_via_gw - send an skb via gateway lookup
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: payload to send
   * @vid: the vid to be used to search the translation table
   *
   * Look up the currently selected gateway. Wrap the given skb into a batman-adv
   * unicast header and send this frame to this gateway node.
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
424
   * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
e300d3146   Linus Lüssing   batman-adv: refin...
425
426
427
428
429
   */
  int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
  			   unsigned short vid)
  {
  	struct batadv_orig_node *orig_node;
f19dc7770   Sven Eckelmann   batman-adv: Remov...
430
  	int ret;
e300d3146   Linus Lüssing   batman-adv: refin...
431
432
  
  	orig_node = batadv_gw_get_selected_orig(bat_priv);
f19dc7770   Sven Eckelmann   batman-adv: Remov...
433
434
435
436
437
438
439
  	ret = batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST_4ADDR,
  				      BATADV_P_DATA, orig_node, vid);
  
  	if (orig_node)
  		batadv_orig_node_put(orig_node);
  
  	return ret;
e300d3146   Linus Lüssing   batman-adv: refin...
440
  }
a65e54813   Linus Lüssing   batman-adv: Intro...
441
442
443
  /**
   * batadv_forw_packet_free - free a forwarding packet
   * @forw_packet: The packet to free
bd687fe41   Sven Eckelmann   batman-adv: use c...
444
   * @dropped: whether the packet is freed because is is dropped
a65e54813   Linus Lüssing   batman-adv: Intro...
445
446
447
448
   *
   * This frees a forwarding packet and releases any resources it might
   * have claimed.
   */
bd687fe41   Sven Eckelmann   batman-adv: use c...
449
450
  void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet,
  			     bool dropped)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
451
  {
bd687fe41   Sven Eckelmann   batman-adv: use c...
452
453
454
455
  	if (dropped)
  		kfree_skb(forw_packet->skb);
  	else
  		consume_skb(forw_packet->skb);
6d5808d4a   Sven Eckelmann   batman-adv: Add m...
456
  	if (forw_packet->if_incoming)
82047ad7f   Sven Eckelmann   batman-adv: Renam...
457
  		batadv_hardif_put(forw_packet->if_incoming);
ef0a937f7   Simon Wunderlich   batman-adv: consi...
458
  	if (forw_packet->if_outgoing)
82047ad7f   Sven Eckelmann   batman-adv: Renam...
459
  		batadv_hardif_put(forw_packet->if_outgoing);
a65e54813   Linus Lüssing   batman-adv: Intro...
460
461
  	if (forw_packet->queue_left)
  		atomic_inc(forw_packet->queue_left);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
462
463
  	kfree(forw_packet);
  }
a65e54813   Linus Lüssing   batman-adv: Intro...
464
465
466
467
468
469
  /**
   * batadv_forw_packet_alloc - allocate a forwarding packet
   * @if_incoming: The (optional) if_incoming to be grabbed
   * @if_outgoing: The (optional) if_outgoing to be grabbed
   * @queue_left: The (optional) queue counter to decrease
   * @bat_priv: The bat_priv for the mesh of this forw_packet
99ba18ef0   Linus Lüssing   batman-adv: priva...
470
   * @skb: The raw packet this forwarding packet shall contain
a65e54813   Linus Lüssing   batman-adv: Intro...
471
472
473
474
475
476
477
478
479
480
481
   *
   * Allocates a forwarding packet and tries to get a reference to the
   * (optional) if_incoming, if_outgoing and queue_left. If queue_left
   * is NULL then bat_priv is optional, too.
   *
   * Return: An allocated forwarding packet on success, NULL otherwise.
   */
  struct batadv_forw_packet *
  batadv_forw_packet_alloc(struct batadv_hard_iface *if_incoming,
  			 struct batadv_hard_iface *if_outgoing,
  			 atomic_t *queue_left,
99ba18ef0   Linus Lüssing   batman-adv: priva...
482
483
  			 struct batadv_priv *bat_priv,
  			 struct sk_buff *skb)
a65e54813   Linus Lüssing   batman-adv: Intro...
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  {
  	struct batadv_forw_packet *forw_packet;
  	const char *qname;
  
  	if (queue_left && !batadv_atomic_dec_not_zero(queue_left)) {
  		qname = "unknown";
  
  		if (queue_left == &bat_priv->bcast_queue_left)
  			qname = "bcast";
  
  		if (queue_left == &bat_priv->batman_queue_left)
  			qname = "batman";
  
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  			   "%s queue is full
  ", qname);
  
  		return NULL;
  	}
  
  	forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC);
  	if (!forw_packet)
  		goto err;
  
  	if (if_incoming)
  		kref_get(&if_incoming->refcount);
  
  	if (if_outgoing)
  		kref_get(&if_outgoing->refcount);
9b4aec647   Linus Lüssing   batman-adv: fix r...
513
514
  	INIT_HLIST_NODE(&forw_packet->list);
  	INIT_HLIST_NODE(&forw_packet->cleanup_list);
99ba18ef0   Linus Lüssing   batman-adv: priva...
515
  	forw_packet->skb = skb;
a65e54813   Linus Lüssing   batman-adv: Intro...
516
517
518
519
520
521
522
523
524
525
526
527
528
  	forw_packet->queue_left = queue_left;
  	forw_packet->if_incoming = if_incoming;
  	forw_packet->if_outgoing = if_outgoing;
  	forw_packet->num_packets = 0;
  
  	return forw_packet;
  
  err:
  	if (queue_left)
  		atomic_inc(queue_left);
  
  	return NULL;
  }
9b4aec647   Linus Lüssing   batman-adv: fix r...
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  /**
   * batadv_forw_packet_was_stolen - check whether someone stole this packet
   * @forw_packet: the forwarding packet to check
   *
   * This function checks whether the given forwarding packet was claimed by
   * someone else for free().
   *
   * Return: True if someone stole it, false otherwise.
   */
  static bool
  batadv_forw_packet_was_stolen(struct batadv_forw_packet *forw_packet)
  {
  	return !hlist_unhashed(&forw_packet->cleanup_list);
  }
  
  /**
   * batadv_forw_packet_steal - claim a forw_packet for free()
   * @forw_packet: the forwarding packet to steal
   * @lock: a key to the store to steal from (e.g. forw_{bat,bcast}_list_lock)
   *
   * This function tries to steal a specific forw_packet from global
   * visibility for the purpose of getting it for free(). That means
   * the caller is *not* allowed to requeue it afterwards.
   *
   * Return: True if stealing was successful. False if someone else stole it
   * before us.
   */
  bool batadv_forw_packet_steal(struct batadv_forw_packet *forw_packet,
  			      spinlock_t *lock)
  {
  	/* did purging routine steal it earlier? */
  	spin_lock_bh(lock);
  	if (batadv_forw_packet_was_stolen(forw_packet)) {
  		spin_unlock_bh(lock);
  		return false;
  	}
  
  	hlist_del_init(&forw_packet->list);
  
  	/* Just to spot misuse of this function */
  	hlist_add_fake(&forw_packet->cleanup_list);
  
  	spin_unlock_bh(lock);
  	return true;
  }
  
  /**
   * batadv_forw_packet_list_steal - claim a list of forward packets for free()
   * @forw_list: the to be stolen forward packets
   * @cleanup_list: a backup pointer, to be able to dispose the packet later
   * @hard_iface: the interface to steal forward packets from
   *
   * This function claims responsibility to free any forw_packet queued on the
   * given hard_iface. If hard_iface is NULL forwarding packets on all hard
   * interfaces will be claimed.
   *
   * The packets are being moved from the forw_list to the cleanup_list and
   * by that allows already running threads to notice the claiming.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
588
  static void
9b4aec647   Linus Lüssing   batman-adv: fix r...
589
590
591
  batadv_forw_packet_list_steal(struct hlist_head *forw_list,
  			      struct hlist_head *cleanup_list,
  			      const struct batadv_hard_iface *hard_iface)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
592
  {
9b4aec647   Linus Lüssing   batman-adv: fix r...
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
  	struct batadv_forw_packet *forw_packet;
  	struct hlist_node *safe_tmp_node;
  
  	hlist_for_each_entry_safe(forw_packet, safe_tmp_node,
  				  forw_list, list) {
  		/* if purge_outstanding_packets() was called with an argument
  		 * we delete only packets belonging to the given interface
  		 */
  		if (hard_iface &&
  		    (forw_packet->if_incoming != hard_iface) &&
  		    (forw_packet->if_outgoing != hard_iface))
  			continue;
  
  		hlist_del(&forw_packet->list);
  		hlist_add_head(&forw_packet->cleanup_list, cleanup_list);
  	}
  }
  
  /**
   * batadv_forw_packet_list_free - free a list of forward packets
   * @head: a list of to be freed forw_packets
   *
   * This function cancels the scheduling of any packet in the provided list,
   * waits for any possibly running packet forwarding thread to finish and
   * finally, safely frees this forward packet.
   *
   * This function might sleep.
   */
  static void batadv_forw_packet_list_free(struct hlist_head *head)
  {
  	struct batadv_forw_packet *forw_packet;
  	struct hlist_node *safe_tmp_node;
  
  	hlist_for_each_entry_safe(forw_packet, safe_tmp_node, head,
  				  cleanup_list) {
  		cancel_delayed_work_sync(&forw_packet->delayed_work);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
629

9b4aec647   Linus Lüssing   batman-adv: fix r...
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
  		hlist_del(&forw_packet->cleanup_list);
  		batadv_forw_packet_free(forw_packet, true);
  	}
  }
  
  /**
   * batadv_forw_packet_queue - try to queue a forwarding packet
   * @forw_packet: the forwarding packet to queue
   * @lock: a key to the store (e.g. forw_{bat,bcast}_list_lock)
   * @head: the shelve to queue it on (e.g. forw_{bat,bcast}_list)
   * @send_time: timestamp (jiffies) when the packet is to be sent
   *
   * This function tries to (re)queue a forwarding packet. Requeuing
   * is prevented if the according interface is shutting down
   * (e.g. if batadv_forw_packet_list_steal() was called for this
   * packet earlier).
   *
   * Calling batadv_forw_packet_queue() after a call to
   * batadv_forw_packet_steal() is forbidden!
   *
   * Caller needs to ensure that forw_packet->delayed_work was initialized.
   */
  static void batadv_forw_packet_queue(struct batadv_forw_packet *forw_packet,
  				     spinlock_t *lock, struct hlist_head *head,
  				     unsigned long send_time)
  {
  	spin_lock_bh(lock);
  
  	/* did purging routine steal it from us? */
  	if (batadv_forw_packet_was_stolen(forw_packet)) {
  		/* If you got it for free() without trouble, then
  		 * don't get back into the queue after stealing...
  		 */
  		WARN_ONCE(hlist_fake(&forw_packet->cleanup_list),
  			  "Requeuing after batadv_forw_packet_steal() not allowed!
  ");
  
  		spin_unlock_bh(lock);
  		return;
  	}
  
  	hlist_del_init(&forw_packet->list);
  	hlist_add_head(&forw_packet->list, head);
  
  	queue_delayed_work(batadv_event_workqueue,
  			   &forw_packet->delayed_work,
  			   send_time - jiffies);
  	spin_unlock_bh(lock);
  }
  
  /**
   * batadv_forw_packet_bcast_queue - try to queue a broadcast packet
   * @bat_priv: the bat priv with all the soft interface information
   * @forw_packet: the forwarding packet to queue
   * @send_time: timestamp (jiffies) when the packet is to be sent
   *
   * This function tries to (re)queue a broadcast packet.
   *
   * Caller needs to ensure that forw_packet->delayed_work was initialized.
   */
  static void
  batadv_forw_packet_bcast_queue(struct batadv_priv *bat_priv,
  			       struct batadv_forw_packet *forw_packet,
  			       unsigned long send_time)
  {
  	batadv_forw_packet_queue(forw_packet, &bat_priv->forw_bcast_list_lock,
  				 &bat_priv->forw_bcast_list, send_time);
  }
  
  /**
   * batadv_forw_packet_ogmv1_queue - try to queue an OGMv1 packet
   * @bat_priv: the bat priv with all the soft interface information
   * @forw_packet: the forwarding packet to queue
   * @send_time: timestamp (jiffies) when the packet is to be sent
   *
   * This function tries to (re)queue an OGMv1 packet.
   *
   * Caller needs to ensure that forw_packet->delayed_work was initialized.
   */
  void batadv_forw_packet_ogmv1_queue(struct batadv_priv *bat_priv,
  				    struct batadv_forw_packet *forw_packet,
  				    unsigned long send_time)
  {
  	batadv_forw_packet_queue(forw_packet, &bat_priv->forw_bat_list_lock,
  				 &bat_priv->forw_bat_list, send_time);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
715
  }
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
716
  /**
7afcbbef6   Sven Eckelmann   batman-adv: Fix k...
717
718
719
720
   * batadv_add_bcast_packet_to_list - queue broadcast packet for multiple sends
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: broadcast packet to add
   * @delay: number of jiffies to wait before sending
3111beed0   Linus Lüssing   batman-adv: Simpl...
721
   * @own_packet: true if it is a self-generated broadcast packet
c6c8fea29   Sven Eckelmann   net: Add batman-a...
722
   *
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
723
724
   * add a broadcast packet to the queue and setup timers. broadcast packets
   * are sent multiple times to increase probability for being received.
c6c8fea29   Sven Eckelmann   net: Add batman-a...
725
726
   *
   * The skb is not consumed, so the caller should make sure that the
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
727
   * skb is freed.
62fe710f6   Sven Eckelmann   batman-adv: Fix k...
728
729
   *
   * Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
730
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
731
  int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
9455e34cb   Sven Eckelmann   batman-adv: Prefi...
732
  				    const struct sk_buff *skb,
3111beed0   Linus Lüssing   batman-adv: Simpl...
733
734
  				    unsigned long delay,
  				    bool own_packet)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
735
  {
422d2f778   Sven Eckelmann   batman-adv: Remov...
736
  	struct batadv_hard_iface *primary_if;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
737
  	struct batadv_forw_packet *forw_packet;
964126901   Sven Eckelmann   batman-adv: Prefi...
738
  	struct batadv_bcast_packet *bcast_packet;
747e4221a   Sven Eckelmann   batman-adv: Add c...
739
  	struct sk_buff *newskb;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
740

e5d89254b   Sven Eckelmann   batman-adv: Prefi...
741
  	primary_if = batadv_primary_if_get_selected(bat_priv);
32ae9b221   Marek Lindner   batman-adv: Make ...
742
  	if (!primary_if)
a65e54813   Linus Lüssing   batman-adv: Intro...
743
  		goto err;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
744

99ba18ef0   Linus Lüssing   batman-adv: priva...
745
746
747
748
749
  	newskb = skb_copy(skb, GFP_ATOMIC);
  	if (!newskb) {
  		batadv_hardif_put(primary_if);
  		goto err;
  	}
a65e54813   Linus Lüssing   batman-adv: Intro...
750
751
  	forw_packet = batadv_forw_packet_alloc(primary_if, NULL,
  					       &bat_priv->bcast_queue_left,
99ba18ef0   Linus Lüssing   batman-adv: priva...
752
  					       bat_priv, newskb);
a65e54813   Linus Lüssing   batman-adv: Intro...
753
  	batadv_hardif_put(primary_if);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
754
  	if (!forw_packet)
a65e54813   Linus Lüssing   batman-adv: Intro...
755
  		goto err_packet_free;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
756
757
  
  	/* as we have a copy now, it is safe to decrease the TTL */
964126901   Sven Eckelmann   batman-adv: Prefi...
758
  	bcast_packet = (struct batadv_bcast_packet *)newskb->data;
a40d9b075   Simon Wunderlich   batman-adv: fix h...
759
  	bcast_packet->ttl--;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
760

3111beed0   Linus Lüssing   batman-adv: Simpl...
761
  	forw_packet->own = own_packet;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
762

724144420   Antonio Quartulli   batman-adv: a del...
763
764
  	INIT_DELAYED_WORK(&forw_packet->delayed_work,
  			  batadv_send_outstanding_bcast_packet);
9b4aec647   Linus Lüssing   batman-adv: fix r...
765
  	batadv_forw_packet_bcast_queue(bat_priv, forw_packet, jiffies + delay);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
766
  	return NETDEV_TX_OK;
a65e54813   Linus Lüssing   batman-adv: Intro...
767
  err_packet_free:
99ba18ef0   Linus Lüssing   batman-adv: priva...
768
  	kfree_skb(newskb);
a65e54813   Linus Lüssing   batman-adv: Intro...
769
  err:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
770
771
  	return NETDEV_TX_BUSY;
  }
e2d9ba435   Linus Lüssing   batman-adv: restr...
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
  /**
   * batadv_forw_packet_bcasts_left - check if a retransmission is necessary
   * @forw_packet: the forwarding packet to check
   * @hard_iface: the interface to check on
   *
   * Checks whether a given packet has any (re)transmissions left on the provided
   * interface.
   *
   * hard_iface may be NULL: In that case the number of transmissions this skb had
   * so far is compared with the maximum amount of retransmissions independent of
   * any interface instead.
   *
   * Return: True if (re)transmissions are left, false otherwise.
   */
  static bool
  batadv_forw_packet_bcasts_left(struct batadv_forw_packet *forw_packet,
  			       struct batadv_hard_iface *hard_iface)
  {
  	unsigned int max;
  
  	if (hard_iface)
  		max = hard_iface->num_bcasts;
  	else
  		max = BATADV_NUM_BCASTS_MAX;
  
  	return BATADV_SKB_CB(forw_packet->skb)->num_bcasts < max;
  }
  
  /**
   * batadv_forw_packet_bcasts_inc - increment retransmission counter of a packet
   * @forw_packet: the packet to increase the counter for
   */
  static void
  batadv_forw_packet_bcasts_inc(struct batadv_forw_packet *forw_packet)
  {
  	BATADV_SKB_CB(forw_packet->skb)->num_bcasts++;
  }
  
  /**
   * batadv_forw_packet_is_rebroadcast - check packet for previous transmissions
   * @forw_packet: the packet to check
   *
   * Return: True if this packet was transmitted before, false otherwise.
   */
  bool batadv_forw_packet_is_rebroadcast(struct batadv_forw_packet *forw_packet)
  {
  	return BATADV_SKB_CB(forw_packet->skb)->num_bcasts > 0;
  }
bb079c82e   Sven Eckelmann   batman-adv: Prefi...
820
  static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
821
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
822
  	struct batadv_hard_iface *hard_iface;
3111beed0   Linus Lüssing   batman-adv: Simpl...
823
  	struct batadv_hardif_neigh_node *neigh_node;
bbb1f90ef   Sven Eckelmann   batman-adv: Don't...
824
  	struct delayed_work *delayed_work;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
825
  	struct batadv_forw_packet *forw_packet;
3111beed0   Linus Lüssing   batman-adv: Simpl...
826
  	struct batadv_bcast_packet *bcast_packet;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
827
  	struct sk_buff *skb1;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
828
829
  	struct net_device *soft_iface;
  	struct batadv_priv *bat_priv;
9b4aec647   Linus Lüssing   batman-adv: fix r...
830
  	unsigned long send_time = jiffies + msecs_to_jiffies(5);
bd687fe41   Sven Eckelmann   batman-adv: use c...
831
  	bool dropped = false;
3111beed0   Linus Lüssing   batman-adv: Simpl...
832
833
834
  	u8 *neigh_addr;
  	u8 *orig_neigh;
  	int ret = 0;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
835

4ba4bc0f7   Geliang Tang   batman-adv: use t...
836
  	delayed_work = to_delayed_work(work);
56303d34a   Sven Eckelmann   batman-adv: Prefi...
837
838
839
840
  	forw_packet = container_of(delayed_work, struct batadv_forw_packet,
  				   delayed_work);
  	soft_iface = forw_packet->if_incoming->soft_iface;
  	bat_priv = netdev_priv(soft_iface);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
841

bd687fe41   Sven Eckelmann   batman-adv: use c...
842
843
  	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
  		dropped = true;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
844
  		goto out;
bd687fe41   Sven Eckelmann   batman-adv: use c...
845
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
846

bd687fe41   Sven Eckelmann   batman-adv: use c...
847
848
  	if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet)) {
  		dropped = true;
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
849
  		goto out;
bd687fe41   Sven Eckelmann   batman-adv: use c...
850
  	}
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
851

3111beed0   Linus Lüssing   batman-adv: Simpl...
852
  	bcast_packet = (struct batadv_bcast_packet *)forw_packet->skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
853
854
  	/* rebroadcast packet */
  	rcu_read_lock();
3193e8fdf   Sven Eckelmann   batman-adv: Prefi...
855
  	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
e6c10f433   Marek Lindner   batman-adv: renam...
856
  		if (hard_iface->soft_iface != soft_iface)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
857
  			continue;
e2d9ba435   Linus Lüssing   batman-adv: restr...
858
  		if (!batadv_forw_packet_bcasts_left(forw_packet, hard_iface))
caf65bfcc   Matthias Schiffer   batman-adv: send ...
859
  			continue;
3111beed0   Linus Lüssing   batman-adv: Simpl...
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
  		if (forw_packet->own) {
  			neigh_node = NULL;
  		} else {
  			neigh_addr = eth_hdr(forw_packet->skb)->h_source;
  			neigh_node = batadv_hardif_neigh_get(hard_iface,
  							     neigh_addr);
  		}
  
  		orig_neigh = neigh_node ? neigh_node->orig : NULL;
  
  		ret = batadv_hardif_no_broadcast(hard_iface, bcast_packet->orig,
  						 orig_neigh);
  
  		if (ret) {
  			char *type;
  
  			switch (ret) {
  			case BATADV_HARDIF_BCAST_NORECIPIENT:
  				type = "no neighbor";
  				break;
  			case BATADV_HARDIF_BCAST_DUPFWD:
  				type = "single neighbor is source";
  				break;
  			case BATADV_HARDIF_BCAST_DUPORIG:
  				type = "single neighbor is originator";
  				break;
  			default:
  				type = "unknown";
  			}
f25cbb2a6   Colin Ian King   batman-adv: fix v...
889
890
  			batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "BCAST packet from orig %pM on %s suppressed: %s
  ",
3111beed0   Linus Lüssing   batman-adv: Simpl...
891
892
893
894
895
896
897
898
899
900
901
  				   bcast_packet->orig,
  				   hard_iface->net_dev->name, type);
  
  			if (neigh_node)
  				batadv_hardif_neigh_put(neigh_node);
  
  			continue;
  		}
  
  		if (neigh_node)
  			batadv_hardif_neigh_put(neigh_node);
273534468   Sven Eckelmann   batman-adv: Check...
902
903
  		if (!kref_get_unless_zero(&hard_iface->refcount))
  			continue;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
904
905
906
  		/* send a copy of the saved skb */
  		skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
  		if (skb1)
95d392784   Antonio Quartulli   batman-adv: keep ...
907
  			batadv_send_broadcast_skb(skb1, hard_iface);
273534468   Sven Eckelmann   batman-adv: Check...
908
909
  
  		batadv_hardif_put(hard_iface);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
910
911
  	}
  	rcu_read_unlock();
e2d9ba435   Linus Lüssing   batman-adv: restr...
912
  	batadv_forw_packet_bcasts_inc(forw_packet);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
913
914
  
  	/* if we still have some more bcasts to send */
e2d9ba435   Linus Lüssing   batman-adv: restr...
915
  	if (batadv_forw_packet_bcasts_left(forw_packet, NULL)) {
9b4aec647   Linus Lüssing   batman-adv: fix r...
916
917
  		batadv_forw_packet_bcast_queue(bat_priv, forw_packet,
  					       send_time);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
918
919
920
921
  		return;
  	}
  
  out:
9b4aec647   Linus Lüssing   batman-adv: fix r...
922
923
924
925
  	/* do we get something for free()? */
  	if (batadv_forw_packet_steal(forw_packet,
  				     &bat_priv->forw_bcast_list_lock))
  		batadv_forw_packet_free(forw_packet, dropped);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
926
  }
9b4aec647   Linus Lüssing   batman-adv: fix r...
927
928
929
930
931
932
933
934
935
936
937
  /**
   * batadv_purge_outstanding_packets - stop/purge scheduled bcast/OGMv1 packets
   * @bat_priv: the bat priv with all the soft interface information
   * @hard_iface: the hard interface to cancel and purge bcast/ogm packets on
   *
   * This method cancels and purges any broadcast and OGMv1 packet on the given
   * hard_iface. If hard_iface is NULL, broadcast and OGMv1 packets on all hard
   * interfaces will be canceled and purged.
   *
   * This function might sleep.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
938
939
940
  void
  batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
  				 const struct batadv_hard_iface *hard_iface)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
941
  {
9b4aec647   Linus Lüssing   batman-adv: fix r...
942
  	struct hlist_head head = HLIST_HEAD_INIT;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
943

e6c10f433   Marek Lindner   batman-adv: renam...
944
  	if (hard_iface)
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
945
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
22f0502ed   Sven Eckelmann   batman-adv: Print...
946
947
948
  			   "%s(): %s
  ",
  			   __func__, hard_iface->net_dev->name);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
949
  	else
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
950
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
22f0502ed   Sven Eckelmann   batman-adv: Print...
951
952
  			   "%s()
  ", __func__);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
953

9b4aec647   Linus Lüssing   batman-adv: fix r...
954
  	/* claim bcast list for free() */
c6c8fea29   Sven Eckelmann   net: Add batman-a...
955
  	spin_lock_bh(&bat_priv->forw_bcast_list_lock);
9b4aec647   Linus Lüssing   batman-adv: fix r...
956
957
  	batadv_forw_packet_list_steal(&bat_priv->forw_bcast_list, &head,
  				      hard_iface);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
958
  	spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
9b4aec647   Linus Lüssing   batman-adv: fix r...
959
  	/* claim batman packet list for free() */
c6c8fea29   Sven Eckelmann   net: Add batman-a...
960
  	spin_lock_bh(&bat_priv->forw_bat_list_lock);
9b4aec647   Linus Lüssing   batman-adv: fix r...
961
962
  	batadv_forw_packet_list_steal(&bat_priv->forw_bat_list, &head,
  				      hard_iface);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
963
  	spin_unlock_bh(&bat_priv->forw_bat_list_lock);
9b4aec647   Linus Lüssing   batman-adv: fix r...
964
965
966
  
  	/* then cancel or wait for packet workers to finish and free */
  	batadv_forw_packet_list_free(&head);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
967
  }