aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/Makefile1
-rw-r--r--net/batman-adv/aggregation.c266
-rw-r--r--net/batman-adv/aggregation.h42
-rw-r--r--net/batman-adv/bat_iv_ogm.c502
-rw-r--r--net/batman-adv/bat_ogm.h2
-rw-r--r--net/batman-adv/hard-interface.c2
-rw-r--r--net/batman-adv/send.c297
-rw-r--r--net/batman-adv/send.h9
8 files changed, 522 insertions, 599 deletions
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 32935986af3b..ce6861166499 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -19,7 +19,6 @@
19# 19#
20 20
21obj-$(CONFIG_BATMAN_ADV) += batman-adv.o 21obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
22batman-adv-y += aggregation.o
23batman-adv-y += bat_debugfs.o 22batman-adv-y += bat_debugfs.o
24batman-adv-y += bat_iv_ogm.o 23batman-adv-y += bat_iv_ogm.o
25batman-adv-y += bat_sysfs.o 24batman-adv-y += bat_sysfs.o
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
deleted file mode 100644
index 4716c9386f21..000000000000
--- a/net/batman-adv/aggregation.c
+++ /dev/null
@@ -1,266 +0,0 @@
1/*
2 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "translation-table.h"
24#include "aggregation.h"
25#include "send.h"
26#include "routing.h"
27#include "hard-interface.h"
28
29/* return true if new_packet can be aggregated with forw_packet */
30static bool can_aggregate_with(const struct batman_ogm_packet
31 *new_batman_ogm_packet,
32 struct bat_priv *bat_priv,
33 int packet_len,
34 unsigned long send_time,
35 bool directlink,
36 const struct hard_iface *if_incoming,
37 const struct forw_packet *forw_packet)
38{
39 struct batman_ogm_packet *batman_ogm_packet =
40 (struct batman_ogm_packet *)forw_packet->skb->data;
41 int aggregated_bytes = forw_packet->packet_len + packet_len;
42 struct hard_iface *primary_if = NULL;
43 bool res = false;
44
45 /**
46 * we can aggregate the current packet to this aggregated packet
47 * if:
48 *
49 * - the send time is within our MAX_AGGREGATION_MS time
50 * - the resulting packet wont be bigger than
51 * MAX_AGGREGATION_BYTES
52 */
53
54 if (time_before(send_time, forw_packet->send_time) &&
55 time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
56 forw_packet->send_time) &&
57 (aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
58
59 /**
60 * check aggregation compatibility
61 * -> direct link packets are broadcasted on
62 * their interface only
63 * -> aggregate packet if the current packet is
64 * a "global" packet as well as the base
65 * packet
66 */
67
68 primary_if = primary_if_get_selected(bat_priv);
69 if (!primary_if)
70 goto out;
71
72 /* packets without direct link flag and high TTL
73 * are flooded through the net */
74 if ((!directlink) &&
75 (!(batman_ogm_packet->flags & DIRECTLINK)) &&
76 (batman_ogm_packet->ttl != 1) &&
77
78 /* own packets originating non-primary
79 * interfaces leave only that interface */
80 ((!forw_packet->own) ||
81 (forw_packet->if_incoming == primary_if))) {
82 res = true;
83 goto out;
84 }
85
86 /* if the incoming packet is sent via this one
87 * interface only - we still can aggregate */
88 if ((directlink) &&
89 (new_batman_ogm_packet->ttl == 1) &&
90 (forw_packet->if_incoming == if_incoming) &&
91
92 /* packets from direct neighbors or
93 * own secondary interface packets
94 * (= secondary interface packets in general) */
95 (batman_ogm_packet->flags & DIRECTLINK ||
96 (forw_packet->own &&
97 forw_packet->if_incoming != primary_if))) {
98 res = true;
99 goto out;
100 }
101 }
102
103out:
104 if (primary_if)
105 hardif_free_ref(primary_if);
106 return res;
107}
108
109/* create a new aggregated packet and add this packet to it */
110static void new_aggregated_packet(const unsigned char *packet_buff,
111 int packet_len, unsigned long send_time,
112 bool direct_link,
113 struct hard_iface *if_incoming,
114 int own_packet)
115{
116 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
117 struct forw_packet *forw_packet_aggr;
118 unsigned char *skb_buff;
119
120 if (!atomic_inc_not_zero(&if_incoming->refcount))
121 return;
122
123 /* own packet should always be scheduled */
124 if (!own_packet) {
125 if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
126 bat_dbg(DBG_BATMAN, bat_priv,
127 "batman packet queue full\n");
128 goto out;
129 }
130 }
131
132 forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC);
133 if (!forw_packet_aggr) {
134 if (!own_packet)
135 atomic_inc(&bat_priv->batman_queue_left);
136 goto out;
137 }
138
139 if ((atomic_read(&bat_priv->aggregated_ogms)) &&
140 (packet_len < MAX_AGGREGATION_BYTES))
141 forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES +
142 sizeof(struct ethhdr));
143 else
144 forw_packet_aggr->skb = dev_alloc_skb(packet_len +
145 sizeof(struct ethhdr));
146
147 if (!forw_packet_aggr->skb) {
148 if (!own_packet)
149 atomic_inc(&bat_priv->batman_queue_left);
150 kfree(forw_packet_aggr);
151 goto out;
152 }
153 skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
154
155 INIT_HLIST_NODE(&forw_packet_aggr->list);
156
157 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
158 forw_packet_aggr->packet_len = packet_len;
159 memcpy(skb_buff, packet_buff, packet_len);
160
161 forw_packet_aggr->own = own_packet;
162 forw_packet_aggr->if_incoming = if_incoming;
163 forw_packet_aggr->num_packets = 0;
164 forw_packet_aggr->direct_link_flags = NO_FLAGS;
165 forw_packet_aggr->send_time = send_time;
166
167 /* save packet direct link flag status */
168 if (direct_link)
169 forw_packet_aggr->direct_link_flags |= 1;
170
171 /* add new packet to packet list */
172 spin_lock_bh(&bat_priv->forw_bat_list_lock);
173 hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
174 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
175
176 /* start timer for this packet */
177 INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
178 send_outstanding_bat_packet);
179 queue_delayed_work(bat_event_workqueue,
180 &forw_packet_aggr->delayed_work,
181 send_time - jiffies);
182
183 return;
184out:
185 hardif_free_ref(if_incoming);
186}
187
188/* aggregate a new packet into the existing aggregation */
189static void aggregate(struct forw_packet *forw_packet_aggr,
190 const unsigned char *packet_buff, int packet_len,
191 bool direct_link)
192{
193 unsigned char *skb_buff;
194
195 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
196 memcpy(skb_buff, packet_buff, packet_len);
197 forw_packet_aggr->packet_len += packet_len;
198 forw_packet_aggr->num_packets++;
199
200 /* save packet direct link flag status */
201 if (direct_link)
202 forw_packet_aggr->direct_link_flags |=
203 (1 << forw_packet_aggr->num_packets);
204}
205
206void add_bat_packet_to_list(struct bat_priv *bat_priv,
207 unsigned char *packet_buff, int packet_len,
208 struct hard_iface *if_incoming, int own_packet,
209 unsigned long send_time)
210{
211 /**
212 * _aggr -> pointer to the packet we want to aggregate with
213 * _pos -> pointer to the position in the queue
214 */
215 struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL;
216 struct hlist_node *tmp_node;
217 struct batman_ogm_packet *batman_ogm_packet;
218 bool direct_link;
219
220 batman_ogm_packet = (struct batman_ogm_packet *)packet_buff;
221 direct_link = batman_ogm_packet->flags & DIRECTLINK ? 1 : 0;
222
223 /* find position for the packet in the forward queue */
224 spin_lock_bh(&bat_priv->forw_bat_list_lock);
225 /* own packets are not to be aggregated */
226 if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) {
227 hlist_for_each_entry(forw_packet_pos, tmp_node,
228 &bat_priv->forw_bat_list, list) {
229 if (can_aggregate_with(batman_ogm_packet,
230 bat_priv,
231 packet_len,
232 send_time,
233 direct_link,
234 if_incoming,
235 forw_packet_pos)) {
236 forw_packet_aggr = forw_packet_pos;
237 break;
238 }
239 }
240 }
241
242 /* nothing to aggregate with - either aggregation disabled or no
243 * suitable aggregation packet found */
244 if (!forw_packet_aggr) {
245 /* the following section can run without the lock */
246 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
247
248 /**
249 * if we could not aggregate this packet with one of the others
250 * we hold it back for a while, so that it might be aggregated
251 * later on
252 */
253 if ((!own_packet) &&
254 (atomic_read(&bat_priv->aggregated_ogms)))
255 send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
256
257 new_aggregated_packet(packet_buff, packet_len,
258 send_time, direct_link,
259 if_incoming, own_packet);
260 } else {
261 aggregate(forw_packet_aggr,
262 packet_buff, packet_len,
263 direct_link);
264 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
265 }
266}
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
deleted file mode 100644
index 7a92e4c69ed0..000000000000
--- a/net/batman-adv/aggregation.h
+++ /dev/null
@@ -1,42 +0,0 @@
1/*
2 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#ifndef _NET_BATMAN_ADV_AGGREGATION_H_
23#define _NET_BATMAN_ADV_AGGREGATION_H_
24
25#include "main.h"
26
27/* is there another aggregated packet here? */
28static inline int aggregated_packet(int buff_pos, int packet_len,
29 int tt_num_changes)
30{
31 int next_buff_pos = buff_pos + BATMAN_OGM_LEN + tt_len(tt_num_changes);
32
33 return (next_buff_pos <= packet_len) &&
34 (next_buff_pos <= MAX_AGGREGATION_BYTES);
35}
36
37void add_bat_packet_to_list(struct bat_priv *bat_priv,
38 unsigned char *packet_buff, int packet_len,
39 struct hard_iface *if_incoming, int own_packet,
40 unsigned long send_time);
41
42#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 468bd5e1f7f5..3512e251545b 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -67,6 +67,27 @@ void bat_ogm_update_mac(struct hard_iface *hard_iface)
67 hard_iface->net_dev->dev_addr, ETH_ALEN); 67 hard_iface->net_dev->dev_addr, ETH_ALEN);
68} 68}
69 69
70/* when do we schedule our own ogm to be sent */
71static unsigned long bat_ogm_emit_send_time(const struct bat_priv *bat_priv)
72{
73 return jiffies + msecs_to_jiffies(
74 atomic_read(&bat_priv->orig_interval) -
75 JITTER + (random32() % 2*JITTER));
76}
77
78/* when do we schedule a ogm packet to be sent */
79static unsigned long bat_ogm_fwd_send_time(void)
80{
81 return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
82}
83
84/* apply hop penalty for a normal link */
85static uint8_t hop_penalty(uint8_t tq, const struct bat_priv *bat_priv)
86{
87 int hop_penalty = atomic_read(&bat_priv->hop_penalty);
88 return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE);
89}
90
70/* is there another aggregated packet here? */ 91/* is there another aggregated packet here? */
71static int bat_ogm_aggr_packet(int buff_pos, int packet_len, 92static int bat_ogm_aggr_packet(int buff_pos, int packet_len,
72 int tt_num_changes) 93 int tt_num_changes)
@@ -77,6 +98,480 @@ static int bat_ogm_aggr_packet(int buff_pos, int packet_len,
77 (next_buff_pos <= MAX_AGGREGATION_BYTES); 98 (next_buff_pos <= MAX_AGGREGATION_BYTES);
78} 99}
79 100
101/* send a batman ogm to a given interface */
102static void bat_ogm_send_to_if(struct forw_packet *forw_packet,
103 struct hard_iface *hard_iface)
104{
105 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
106 char *fwd_str;
107 uint8_t packet_num;
108 int16_t buff_pos;
109 struct batman_ogm_packet *batman_ogm_packet;
110 struct sk_buff *skb;
111
112 if (hard_iface->if_status != IF_ACTIVE)
113 return;
114
115 packet_num = 0;
116 buff_pos = 0;
117 batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data;
118
119 /* adjust all flags and log packets */
120 while (bat_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
121 batman_ogm_packet->tt_num_changes)) {
122
123 /* we might have aggregated direct link packets with an
124 * ordinary base packet */
125 if ((forw_packet->direct_link_flags & (1 << packet_num)) &&
126 (forw_packet->if_incoming == hard_iface))
127 batman_ogm_packet->flags |= DIRECTLINK;
128 else
129 batman_ogm_packet->flags &= ~DIRECTLINK;
130
131 fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
132 "Sending own" :
133 "Forwarding"));
134 bat_dbg(DBG_BATMAN, bat_priv,
135 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
136 " IDF %s, ttvn %d) on interface %s [%pM]\n",
137 fwd_str, (packet_num > 0 ? "aggregated " : ""),
138 batman_ogm_packet->orig,
139 ntohl(batman_ogm_packet->seqno),
140 batman_ogm_packet->tq, batman_ogm_packet->ttl,
141 (batman_ogm_packet->flags & DIRECTLINK ?
142 "on" : "off"),
143 batman_ogm_packet->ttvn, hard_iface->net_dev->name,
144 hard_iface->net_dev->dev_addr);
145
146 buff_pos += BATMAN_OGM_LEN +
147 tt_len(batman_ogm_packet->tt_num_changes);
148 packet_num++;
149 batman_ogm_packet = (struct batman_ogm_packet *)
150 (forw_packet->skb->data + buff_pos);
151 }
152
153 /* create clone because function is called more than once */
154 skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
155 if (skb)
156 send_skb_packet(skb, hard_iface, broadcast_addr);
157}
158
159/* send a batman ogm packet */
160void bat_ogm_emit(struct forw_packet *forw_packet)
161{
162 struct hard_iface *hard_iface;
163 struct net_device *soft_iface;
164 struct bat_priv *bat_priv;
165 struct hard_iface *primary_if = NULL;
166 struct batman_ogm_packet *batman_ogm_packet;
167 unsigned char directlink;
168
169 batman_ogm_packet = (struct batman_ogm_packet *)
170 (forw_packet->skb->data);
171 directlink = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
172
173 if (!forw_packet->if_incoming) {
174 pr_err("Error - can't forward packet: incoming iface not "
175 "specified\n");
176 goto out;
177 }
178
179 soft_iface = forw_packet->if_incoming->soft_iface;
180 bat_priv = netdev_priv(soft_iface);
181
182 if (forw_packet->if_incoming->if_status != IF_ACTIVE)
183 goto out;
184
185 primary_if = primary_if_get_selected(bat_priv);
186 if (!primary_if)
187 goto out;
188
189 /* multihomed peer assumed */
190 /* non-primary OGMs are only broadcasted on their interface */
191 if ((directlink && (batman_ogm_packet->ttl == 1)) ||
192 (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
193
194 /* FIXME: what about aggregated packets ? */
195 bat_dbg(DBG_BATMAN, bat_priv,
196 "%s packet (originator %pM, seqno %d, TTL %d) "
197 "on interface %s [%pM]\n",
198 (forw_packet->own ? "Sending own" : "Forwarding"),
199 batman_ogm_packet->orig,
200 ntohl(batman_ogm_packet->seqno),
201 batman_ogm_packet->ttl,
202 forw_packet->if_incoming->net_dev->name,
203 forw_packet->if_incoming->net_dev->dev_addr);
204
205 /* skb is only used once and than forw_packet is free'd */
206 send_skb_packet(forw_packet->skb, forw_packet->if_incoming,
207 broadcast_addr);
208 forw_packet->skb = NULL;
209
210 goto out;
211 }
212
213 /* broadcast on every interface */
214 rcu_read_lock();
215 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
216 if (hard_iface->soft_iface != soft_iface)
217 continue;
218
219 bat_ogm_send_to_if(forw_packet, hard_iface);
220 }
221 rcu_read_unlock();
222
223out:
224 if (primary_if)
225 hardif_free_ref(primary_if);
226}
227
228/* return true if new_packet can be aggregated with forw_packet */
229static bool bat_ogm_can_aggregate(const struct batman_ogm_packet
230 *new_batman_ogm_packet,
231 struct bat_priv *bat_priv,
232 int packet_len, unsigned long send_time,
233 bool directlink,
234 const struct hard_iface *if_incoming,
235 const struct forw_packet *forw_packet)
236{
237 struct batman_ogm_packet *batman_ogm_packet;
238 int aggregated_bytes = forw_packet->packet_len + packet_len;
239 struct hard_iface *primary_if = NULL;
240 bool res = false;
241
242 batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data;
243
244 /**
245 * we can aggregate the current packet to this aggregated packet
246 * if:
247 *
248 * - the send time is within our MAX_AGGREGATION_MS time
249 * - the resulting packet wont be bigger than
250 * MAX_AGGREGATION_BYTES
251 */
252
253 if (time_before(send_time, forw_packet->send_time) &&
254 time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
255 forw_packet->send_time) &&
256 (aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
257
258 /**
259 * check aggregation compatibility
260 * -> direct link packets are broadcasted on
261 * their interface only
262 * -> aggregate packet if the current packet is
263 * a "global" packet as well as the base
264 * packet
265 */
266
267 primary_if = primary_if_get_selected(bat_priv);
268 if (!primary_if)
269 goto out;
270
271 /* packets without direct link flag and high TTL
272 * are flooded through the net */
273 if ((!directlink) &&
274 (!(batman_ogm_packet->flags & DIRECTLINK)) &&
275 (batman_ogm_packet->ttl != 1) &&
276
277 /* own packets originating non-primary
278 * interfaces leave only that interface */
279 ((!forw_packet->own) ||
280 (forw_packet->if_incoming == primary_if))) {
281 res = true;
282 goto out;
283 }
284
285 /* if the incoming packet is sent via this one
286 * interface only - we still can aggregate */
287 if ((directlink) &&
288 (new_batman_ogm_packet->ttl == 1) &&
289 (forw_packet->if_incoming == if_incoming) &&
290
291 /* packets from direct neighbors or
292 * own secondary interface packets
293 * (= secondary interface packets in general) */
294 (batman_ogm_packet->flags & DIRECTLINK ||
295 (forw_packet->own &&
296 forw_packet->if_incoming != primary_if))) {
297 res = true;
298 goto out;
299 }
300 }
301
302out:
303 if (primary_if)
304 hardif_free_ref(primary_if);
305 return res;
306}
307
308/* create a new aggregated packet and add this packet to it */
309static void bat_ogm_aggregate_new(const unsigned char *packet_buff,
310 int packet_len, unsigned long send_time,
311 bool direct_link,
312 struct hard_iface *if_incoming,
313 int own_packet)
314{
315 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
316 struct forw_packet *forw_packet_aggr;
317 unsigned char *skb_buff;
318
319 if (!atomic_inc_not_zero(&if_incoming->refcount))
320 return;
321
322 /* own packet should always be scheduled */
323 if (!own_packet) {
324 if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
325 bat_dbg(DBG_BATMAN, bat_priv,
326 "batman packet queue full\n");
327 goto out;
328 }
329 }
330
331 forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC);
332 if (!forw_packet_aggr) {
333 if (!own_packet)
334 atomic_inc(&bat_priv->batman_queue_left);
335 goto out;
336 }
337
338 if ((atomic_read(&bat_priv->aggregated_ogms)) &&
339 (packet_len < MAX_AGGREGATION_BYTES))
340 forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES +
341 sizeof(struct ethhdr));
342 else
343 forw_packet_aggr->skb = dev_alloc_skb(packet_len +
344 sizeof(struct ethhdr));
345
346 if (!forw_packet_aggr->skb) {
347 if (!own_packet)
348 atomic_inc(&bat_priv->batman_queue_left);
349 kfree(forw_packet_aggr);
350 goto out;
351 }
352 skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
353
354 INIT_HLIST_NODE(&forw_packet_aggr->list);
355
356 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
357 forw_packet_aggr->packet_len = packet_len;
358 memcpy(skb_buff, packet_buff, packet_len);
359
360 forw_packet_aggr->own = own_packet;
361 forw_packet_aggr->if_incoming = if_incoming;
362 forw_packet_aggr->num_packets = 0;
363 forw_packet_aggr->direct_link_flags = NO_FLAGS;
364 forw_packet_aggr->send_time = send_time;
365
366 /* save packet direct link flag status */
367 if (direct_link)
368 forw_packet_aggr->direct_link_flags |= 1;
369
370 /* add new packet to packet list */
371 spin_lock_bh(&bat_priv->forw_bat_list_lock);
372 hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
373 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
374
375 /* start timer for this packet */
376 INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
377 send_outstanding_bat_ogm_packet);
378 queue_delayed_work(bat_event_workqueue,
379 &forw_packet_aggr->delayed_work,
380 send_time - jiffies);
381
382 return;
383out:
384 hardif_free_ref(if_incoming);
385}
386
387/* aggregate a new packet into the existing ogm packet */
388static void bat_ogm_aggregate(struct forw_packet *forw_packet_aggr,
389 const unsigned char *packet_buff,
390 int packet_len, bool direct_link)
391{
392 unsigned char *skb_buff;
393
394 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
395 memcpy(skb_buff, packet_buff, packet_len);
396 forw_packet_aggr->packet_len += packet_len;
397 forw_packet_aggr->num_packets++;
398
399 /* save packet direct link flag status */
400 if (direct_link)
401 forw_packet_aggr->direct_link_flags |=
402 (1 << forw_packet_aggr->num_packets);
403}
404
405static void bat_ogm_queue_add(struct bat_priv *bat_priv,
406 unsigned char *packet_buff,
407 int packet_len, struct hard_iface *if_incoming,
408 int own_packet, unsigned long send_time)
409{
410 /**
411 * _aggr -> pointer to the packet we want to aggregate with
412 * _pos -> pointer to the position in the queue
413 */
414 struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL;
415 struct hlist_node *tmp_node;
416 struct batman_ogm_packet *batman_ogm_packet;
417 bool direct_link;
418
419 batman_ogm_packet = (struct batman_ogm_packet *)packet_buff;
420 direct_link = batman_ogm_packet->flags & DIRECTLINK ? 1 : 0;
421
422 /* find position for the packet in the forward queue */
423 spin_lock_bh(&bat_priv->forw_bat_list_lock);
424 /* own packets are not to be aggregated */
425 if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) {
426 hlist_for_each_entry(forw_packet_pos, tmp_node,
427 &bat_priv->forw_bat_list, list) {
428 if (bat_ogm_can_aggregate(batman_ogm_packet,
429 bat_priv, packet_len,
430 send_time, direct_link,
431 if_incoming,
432 forw_packet_pos)) {
433 forw_packet_aggr = forw_packet_pos;
434 break;
435 }
436 }
437 }
438
439 /* nothing to aggregate with - either aggregation disabled or no
440 * suitable aggregation packet found */
441 if (!forw_packet_aggr) {
442 /* the following section can run without the lock */
443 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
444
445 /**
446 * if we could not aggregate this packet with one of the others
447 * we hold it back for a while, so that it might be aggregated
448 * later on
449 */
450 if ((!own_packet) &&
451 (atomic_read(&bat_priv->aggregated_ogms)))
452 send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
453
454 bat_ogm_aggregate_new(packet_buff, packet_len,
455 send_time, direct_link,
456 if_incoming, own_packet);
457 } else {
458 bat_ogm_aggregate(forw_packet_aggr, packet_buff, packet_len,
459 direct_link);
460 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
461 }
462}
463
464static void bat_ogm_forward(struct orig_node *orig_node,
465 const struct ethhdr *ethhdr,
466 struct batman_ogm_packet *batman_ogm_packet,
467 int directlink, struct hard_iface *if_incoming)
468{
469 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
470 struct neigh_node *router;
471 uint8_t in_tq, in_ttl, tq_avg = 0;
472 uint8_t tt_num_changes;
473
474 if (batman_ogm_packet->ttl <= 1) {
475 bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
476 return;
477 }
478
479 router = orig_node_get_router(orig_node);
480
481 in_tq = batman_ogm_packet->tq;
482 in_ttl = batman_ogm_packet->ttl;
483 tt_num_changes = batman_ogm_packet->tt_num_changes;
484
485 batman_ogm_packet->ttl--;
486 memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
487
488 /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
489 * of our best tq value */
490 if (router && router->tq_avg != 0) {
491
492 /* rebroadcast ogm of best ranking neighbor as is */
493 if (!compare_eth(router->addr, ethhdr->h_source)) {
494 batman_ogm_packet->tq = router->tq_avg;
495
496 if (router->last_ttl)
497 batman_ogm_packet->ttl = router->last_ttl - 1;
498 }
499
500 tq_avg = router->tq_avg;
501 }
502
503 if (router)
504 neigh_node_free_ref(router);
505
506 /* apply hop penalty */
507 batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv);
508
509 bat_dbg(DBG_BATMAN, bat_priv,
510 "Forwarding packet: tq_orig: %i, tq_avg: %i, "
511 "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
512 in_tq, tq_avg, batman_ogm_packet->tq, in_ttl - 1,
513 batman_ogm_packet->ttl);
514
515 batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno);
516 batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc);
517
518 /* switch of primaries first hop flag when forwarding */
519 batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP;
520 if (directlink)
521 batman_ogm_packet->flags |= DIRECTLINK;
522 else
523 batman_ogm_packet->flags &= ~DIRECTLINK;
524
525 bat_ogm_queue_add(bat_priv, (unsigned char *)batman_ogm_packet,
526 BATMAN_OGM_LEN + tt_len(tt_num_changes),
527 if_incoming, 0, bat_ogm_fwd_send_time());
528}
529
530void bat_ogm_schedule(struct hard_iface *hard_iface, int tt_num_changes)
531{
532 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
533 struct batman_ogm_packet *batman_ogm_packet;
534 struct hard_iface *primary_if;
535 int vis_server;
536
537 vis_server = atomic_read(&bat_priv->vis_mode);
538 primary_if = primary_if_get_selected(bat_priv);
539
540 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
541
542 /* change sequence number to network order */
543 batman_ogm_packet->seqno =
544 htonl((uint32_t)atomic_read(&hard_iface->seqno));
545
546 batman_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn);
547 batman_ogm_packet->tt_crc = htons((uint16_t)
548 atomic_read(&bat_priv->tt_crc));
549 if (tt_num_changes >= 0)
550 batman_ogm_packet->tt_num_changes = tt_num_changes;
551
552 if (vis_server == VIS_TYPE_SERVER_SYNC)
553 batman_ogm_packet->flags |= VIS_SERVER;
554 else
555 batman_ogm_packet->flags &= ~VIS_SERVER;
556
557 if ((hard_iface == primary_if) &&
558 (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
559 batman_ogm_packet->gw_flags =
560 (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
561 else
562 batman_ogm_packet->gw_flags = NO_FLAGS;
563
564 atomic_inc(&hard_iface->seqno);
565
566 slide_own_bcast_window(hard_iface);
567 bat_ogm_queue_add(bat_priv, hard_iface->packet_buff,
568 hard_iface->packet_len, hard_iface, 1,
569 bat_ogm_emit_send_time(bat_priv));
570
571 if (primary_if)
572 hardif_free_ref(primary_if);
573}
574
80static void bat_ogm_orig_update(struct bat_priv *bat_priv, 575static void bat_ogm_orig_update(struct bat_priv *bat_priv,
81 struct orig_node *orig_node, 576 struct orig_node *orig_node,
82 const struct ethhdr *ethhdr, 577 const struct ethhdr *ethhdr,
@@ -605,8 +1100,8 @@ static void bat_ogm_process(const struct ethhdr *ethhdr,
605 if (is_single_hop_neigh) { 1100 if (is_single_hop_neigh) {
606 1101
607 /* mark direct link on incoming interface */ 1102 /* mark direct link on incoming interface */
608 schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, 1103 bat_ogm_forward(orig_node, ethhdr, batman_ogm_packet,
609 1, if_incoming); 1104 1, if_incoming);
610 1105
611 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " 1106 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
612 "rebroadcast neighbor packet with direct link flag\n"); 1107 "rebroadcast neighbor packet with direct link flag\n");
@@ -628,8 +1123,7 @@ static void bat_ogm_process(const struct ethhdr *ethhdr,
628 1123
629 bat_dbg(DBG_BATMAN, bat_priv, 1124 bat_dbg(DBG_BATMAN, bat_priv,
630 "Forwarding packet: rebroadcast originator packet\n"); 1125 "Forwarding packet: rebroadcast originator packet\n");
631 schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, 1126 bat_ogm_forward(orig_node, ethhdr, batman_ogm_packet, 0, if_incoming);
632 0, if_incoming);
633 1127
634out_neigh: 1128out_neigh:
635 if ((orig_neigh_node) && (!is_single_hop_neigh)) 1129 if ((orig_neigh_node) && (!is_single_hop_neigh))
diff --git a/net/batman-adv/bat_ogm.h b/net/batman-adv/bat_ogm.h
index 7809b92500bd..69329c107e28 100644
--- a/net/batman-adv/bat_ogm.h
+++ b/net/batman-adv/bat_ogm.h
@@ -27,6 +27,8 @@
27void bat_ogm_init(struct hard_iface *hard_iface); 27void bat_ogm_init(struct hard_iface *hard_iface);
28void bat_ogm_init_primary(struct hard_iface *hard_iface); 28void bat_ogm_init_primary(struct hard_iface *hard_iface);
29void bat_ogm_update_mac(struct hard_iface *hard_iface); 29void bat_ogm_update_mac(struct hard_iface *hard_iface);
30void bat_ogm_schedule(struct hard_iface *hard_iface, int tt_num_changes);
31void bat_ogm_emit(struct forw_packet *forw_packet);
30void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff, 32void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff,
31 int packet_len, struct hard_iface *if_incoming); 33 int packet_len, struct hard_iface *if_incoming);
32 34
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 2a1558242845..0cc0f04bf397 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -360,7 +360,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
360 hard_iface->net_dev->name); 360 hard_iface->net_dev->name);
361 361
362 /* begin scheduling originator messages on that interface */ 362 /* begin scheduling originator messages on that interface */
363 schedule_own_packet(hard_iface); 363 schedule_bat_ogm(hard_iface);
364 364
365out: 365out:
366 return 0; 366 return 0;
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 40a5fcd67136..8a684eb738ad 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -26,33 +26,12 @@
26#include "soft-interface.h" 26#include "soft-interface.h"
27#include "hard-interface.h" 27#include "hard-interface.h"
28#include "vis.h" 28#include "vis.h"
29#include "aggregation.h"
30#include "gateway_common.h" 29#include "gateway_common.h"
31#include "originator.h" 30#include "originator.h"
31#include "bat_ogm.h"
32 32
33static void send_outstanding_bcast_packet(struct work_struct *work); 33static void send_outstanding_bcast_packet(struct work_struct *work);
34 34
35/* apply hop penalty for a normal link */
36static uint8_t hop_penalty(uint8_t tq, const struct bat_priv *bat_priv)
37{
38 int hop_penalty = atomic_read(&bat_priv->hop_penalty);
39 return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE);
40}
41
42/* when do we schedule our own packet to be sent */
43static unsigned long own_send_time(const struct bat_priv *bat_priv)
44{
45 return jiffies + msecs_to_jiffies(
46 atomic_read(&bat_priv->orig_interval) -
47 JITTER + (random32() % 2*JITTER));
48}
49
50/* when do we schedule a forwarded packet to be sent */
51static unsigned long forward_send_time(void)
52{
53 return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
54}
55
56/* send out an already prepared packet to the given address via the 35/* send out an already prepared packet to the given address via the
57 * specified batman interface */ 36 * specified batman interface */
58int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface, 37int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface,
@@ -99,133 +78,6 @@ send_skb_err:
99 return NET_XMIT_DROP; 78 return NET_XMIT_DROP;
100} 79}
101 80
102/* Send a packet to a given interface */
103static void send_packet_to_if(struct forw_packet *forw_packet,
104 struct hard_iface *hard_iface)
105{
106 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
107 char *fwd_str;
108 uint8_t packet_num;
109 int16_t buff_pos;
110 struct batman_ogm_packet *batman_ogm_packet;
111 struct sk_buff *skb;
112
113 if (hard_iface->if_status != IF_ACTIVE)
114 return;
115
116 packet_num = 0;
117 buff_pos = 0;
118 batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data;
119
120 /* adjust all flags and log packets */
121 while (aggregated_packet(buff_pos,
122 forw_packet->packet_len,
123 batman_ogm_packet->tt_num_changes)) {
124
125 /* we might have aggregated direct link packets with an
126 * ordinary base packet */
127 if ((forw_packet->direct_link_flags & (1 << packet_num)) &&
128 (forw_packet->if_incoming == hard_iface))
129 batman_ogm_packet->flags |= DIRECTLINK;
130 else
131 batman_ogm_packet->flags &= ~DIRECTLINK;
132
133 fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
134 "Sending own" :
135 "Forwarding"));
136 bat_dbg(DBG_BATMAN, bat_priv,
137 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
138 " IDF %s, ttvn %d) on interface %s [%pM]\n",
139 fwd_str, (packet_num > 0 ? "aggregated " : ""),
140 batman_ogm_packet->orig,
141 ntohl(batman_ogm_packet->seqno),
142 batman_ogm_packet->tq, batman_ogm_packet->ttl,
143 (batman_ogm_packet->flags & DIRECTLINK ?
144 "on" : "off"),
145 batman_ogm_packet->ttvn, hard_iface->net_dev->name,
146 hard_iface->net_dev->dev_addr);
147
148 buff_pos += BATMAN_OGM_LEN +
149 tt_len(batman_ogm_packet->tt_num_changes);
150 packet_num++;
151 batman_ogm_packet = (struct batman_ogm_packet *)
152 (forw_packet->skb->data + buff_pos);
153 }
154
155 /* create clone because function is called more than once */
156 skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
157 if (skb)
158 send_skb_packet(skb, hard_iface, broadcast_addr);
159}
160
161/* send a batman packet */
162static void send_packet(struct forw_packet *forw_packet)
163{
164 struct hard_iface *hard_iface;
165 struct net_device *soft_iface;
166 struct bat_priv *bat_priv;
167 struct hard_iface *primary_if = NULL;
168 struct batman_ogm_packet *batman_ogm_packet =
169 (struct batman_ogm_packet *)(forw_packet->skb->data);
170 unsigned char directlink;
171
172 directlink = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
173
174 if (!forw_packet->if_incoming) {
175 pr_err("Error - can't forward packet: incoming iface not "
176 "specified\n");
177 goto out;
178 }
179
180 soft_iface = forw_packet->if_incoming->soft_iface;
181 bat_priv = netdev_priv(soft_iface);
182
183 if (forw_packet->if_incoming->if_status != IF_ACTIVE)
184 goto out;
185
186 primary_if = primary_if_get_selected(bat_priv);
187 if (!primary_if)
188 goto out;
189
190 /* multihomed peer assumed */
191 /* non-primary OGMs are only broadcasted on their interface */
192 if ((directlink && (batman_ogm_packet->ttl == 1)) ||
193 (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
194
195 /* FIXME: what about aggregated packets ? */
196 bat_dbg(DBG_BATMAN, bat_priv,
197 "%s packet (originator %pM, seqno %d, TTL %d) "
198 "on interface %s [%pM]\n",
199 (forw_packet->own ? "Sending own" : "Forwarding"),
200 batman_ogm_packet->orig,
201 ntohl(batman_ogm_packet->seqno),
202 batman_ogm_packet->ttl,
203 forw_packet->if_incoming->net_dev->name,
204 forw_packet->if_incoming->net_dev->dev_addr);
205
206 /* skb is only used once and than forw_packet is free'd */
207 send_skb_packet(forw_packet->skb, forw_packet->if_incoming,
208 broadcast_addr);
209 forw_packet->skb = NULL;
210
211 goto out;
212 }
213
214 /* broadcast on every interface */
215 rcu_read_lock();
216 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
217 if (hard_iface->soft_iface != soft_iface)
218 continue;
219
220 send_packet_to_if(forw_packet, hard_iface);
221 }
222 rcu_read_unlock();
223
224out:
225 if (primary_if)
226 hardif_free_ref(primary_if);
227}
228
229static void realloc_packet_buffer(struct hard_iface *hard_iface, 81static void realloc_packet_buffer(struct hard_iface *hard_iface,
230 int new_len) 82 int new_len)
231{ 83{
@@ -245,11 +97,10 @@ static void realloc_packet_buffer(struct hard_iface *hard_iface,
245} 97}
246 98
247/* when calling this function (hard_iface == primary_if) has to be true */ 99/* when calling this function (hard_iface == primary_if) has to be true */
248static void prepare_packet_buffer(struct bat_priv *bat_priv, 100static int prepare_packet_buffer(struct bat_priv *bat_priv,
249 struct hard_iface *hard_iface) 101 struct hard_iface *hard_iface)
250{ 102{
251 int new_len; 103 int new_len;
252 struct batman_ogm_packet *batman_ogm_packet;
253 104
254 new_len = BATMAN_OGM_LEN + 105 new_len = BATMAN_OGM_LEN +
255 tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes)); 106 tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
@@ -260,45 +111,34 @@ static void prepare_packet_buffer(struct bat_priv *bat_priv,
260 new_len = BATMAN_OGM_LEN; 111 new_len = BATMAN_OGM_LEN;
261 112
262 realloc_packet_buffer(hard_iface, new_len); 113 realloc_packet_buffer(hard_iface, new_len);
263 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
264 114
265 atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv)); 115 atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
266 116
267 /* reset the sending counter */ 117 /* reset the sending counter */
268 atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX); 118 atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
269 119
270 batman_ogm_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv, 120 return tt_changes_fill_buffer(bat_priv,
271 hard_iface->packet_buff + BATMAN_OGM_LEN, 121 hard_iface->packet_buff + BATMAN_OGM_LEN,
272 hard_iface->packet_len - BATMAN_OGM_LEN); 122 hard_iface->packet_len - BATMAN_OGM_LEN);
273
274} 123}
275 124
276static void reset_packet_buffer(struct bat_priv *bat_priv, 125static int reset_packet_buffer(struct bat_priv *bat_priv,
277 struct hard_iface *hard_iface) 126 struct hard_iface *hard_iface)
278{ 127{
279 struct batman_ogm_packet *batman_ogm_packet;
280
281 realloc_packet_buffer(hard_iface, BATMAN_OGM_LEN); 128 realloc_packet_buffer(hard_iface, BATMAN_OGM_LEN);
282 129 return 0;
283 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
284 batman_ogm_packet->tt_num_changes = 0;
285} 130}
286 131
287void schedule_own_packet(struct hard_iface *hard_iface) 132void schedule_bat_ogm(struct hard_iface *hard_iface)
288{ 133{
289 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 134 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
290 struct hard_iface *primary_if; 135 struct hard_iface *primary_if;
291 unsigned long send_time; 136 int tt_num_changes = -1;
292 struct batman_ogm_packet *batman_ogm_packet;
293 int vis_server;
294 137
295 if ((hard_iface->if_status == IF_NOT_IN_USE) || 138 if ((hard_iface->if_status == IF_NOT_IN_USE) ||
296 (hard_iface->if_status == IF_TO_BE_REMOVED)) 139 (hard_iface->if_status == IF_TO_BE_REMOVED))
297 return; 140 return;
298 141
299 vis_server = atomic_read(&bat_priv->vis_mode);
300 primary_if = primary_if_get_selected(bat_priv);
301
302 /** 142 /**
303 * the interface gets activated here to avoid race conditions between 143 * the interface gets activated here to avoid race conditions between
304 * the moment of activating the interface in 144 * the moment of activating the interface in
@@ -309,125 +149,26 @@ void schedule_own_packet(struct hard_iface *hard_iface)
309 if (hard_iface->if_status == IF_TO_BE_ACTIVATED) 149 if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
310 hard_iface->if_status = IF_ACTIVE; 150 hard_iface->if_status = IF_ACTIVE;
311 151
152 primary_if = primary_if_get_selected(bat_priv);
153
312 if (hard_iface == primary_if) { 154 if (hard_iface == primary_if) {
313 /* if at least one change happened */ 155 /* if at least one change happened */
314 if (atomic_read(&bat_priv->tt_local_changes) > 0) { 156 if (atomic_read(&bat_priv->tt_local_changes) > 0) {
315 tt_commit_changes(bat_priv); 157 tt_commit_changes(bat_priv);
316 prepare_packet_buffer(bat_priv, hard_iface); 158 tt_num_changes = prepare_packet_buffer(bat_priv,
159 hard_iface);
317 } 160 }
318 161
319 /* if the changes have been sent often enough */ 162 /* if the changes have been sent often enough */
320 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt)) 163 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
321 reset_packet_buffer(bat_priv, hard_iface); 164 tt_num_changes = reset_packet_buffer(bat_priv,
165 hard_iface);
322 } 166 }
323 167
324 /**
325 * NOTE: packet_buff might just have been re-allocated in
326 * prepare_packet_buffer() or in reset_packet_buffer()
327 */
328 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
329
330 /* change sequence number to network order */
331 batman_ogm_packet->seqno =
332 htonl((uint32_t)atomic_read(&hard_iface->seqno));
333
334 batman_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn);
335 batman_ogm_packet->tt_crc = htons((uint16_t)
336 atomic_read(&bat_priv->tt_crc));
337
338 if (vis_server == VIS_TYPE_SERVER_SYNC)
339 batman_ogm_packet->flags |= VIS_SERVER;
340 else
341 batman_ogm_packet->flags &= ~VIS_SERVER;
342
343 if ((hard_iface == primary_if) &&
344 (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
345 batman_ogm_packet->gw_flags =
346 (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
347 else
348 batman_ogm_packet->gw_flags = NO_FLAGS;
349
350 atomic_inc(&hard_iface->seqno);
351
352 slide_own_bcast_window(hard_iface);
353 send_time = own_send_time(bat_priv);
354 add_bat_packet_to_list(bat_priv,
355 hard_iface->packet_buff,
356 hard_iface->packet_len,
357 hard_iface, 1, send_time);
358
359 if (primary_if) 168 if (primary_if)
360 hardif_free_ref(primary_if); 169 hardif_free_ref(primary_if);
361}
362
363void schedule_forward_packet(struct orig_node *orig_node,
364 const struct ethhdr *ethhdr,
365 struct batman_ogm_packet *batman_ogm_packet,
366 int directlink,
367 struct hard_iface *if_incoming)
368{
369 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
370 struct neigh_node *router;
371 uint8_t in_tq, in_ttl, tq_avg = 0;
372 unsigned long send_time;
373 uint8_t tt_num_changes;
374
375 if (batman_ogm_packet->ttl <= 1) {
376 bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
377 return;
378 }
379
380 router = orig_node_get_router(orig_node);
381
382 in_tq = batman_ogm_packet->tq;
383 in_ttl = batman_ogm_packet->ttl;
384 tt_num_changes = batman_ogm_packet->tt_num_changes;
385
386 batman_ogm_packet->ttl--;
387 memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
388
389 /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
390 * of our best tq value */
391 if (router && router->tq_avg != 0) {
392
393 /* rebroadcast ogm of best ranking neighbor as is */
394 if (!compare_eth(router->addr, ethhdr->h_source)) {
395 batman_ogm_packet->tq = router->tq_avg;
396
397 if (router->last_ttl)
398 batman_ogm_packet->ttl = router->last_ttl - 1;
399 }
400
401 tq_avg = router->tq_avg;
402 }
403
404 if (router)
405 neigh_node_free_ref(router);
406
407 /* apply hop penalty */
408 batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv);
409
410 bat_dbg(DBG_BATMAN, bat_priv,
411 "Forwarding packet: tq_orig: %i, tq_avg: %i, "
412 "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
413 in_tq, tq_avg, batman_ogm_packet->tq, in_ttl - 1,
414 batman_ogm_packet->ttl);
415
416 batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno);
417 batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc);
418
419 /* switch of primaries first hop flag when forwarding */
420 batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP;
421 if (directlink)
422 batman_ogm_packet->flags |= DIRECTLINK;
423 else
424 batman_ogm_packet->flags &= ~DIRECTLINK;
425 170
426 send_time = forward_send_time(); 171 bat_ogm_schedule(hard_iface, tt_num_changes);
427 add_bat_packet_to_list(bat_priv,
428 (unsigned char *)batman_ogm_packet,
429 BATMAN_OGM_LEN + tt_len(tt_num_changes),
430 if_incoming, 0, send_time);
431} 172}
432 173
433static void forw_packet_free(struct forw_packet *forw_packet) 174static void forw_packet_free(struct forw_packet *forw_packet)
@@ -561,7 +302,7 @@ out:
561 atomic_inc(&bat_priv->bcast_queue_left); 302 atomic_inc(&bat_priv->bcast_queue_left);
562} 303}
563 304
564void send_outstanding_bat_packet(struct work_struct *work) 305void send_outstanding_bat_ogm_packet(struct work_struct *work)
565{ 306{
566 struct delayed_work *delayed_work = 307 struct delayed_work *delayed_work =
567 container_of(work, struct delayed_work, work); 308 container_of(work, struct delayed_work, work);
@@ -577,7 +318,7 @@ void send_outstanding_bat_packet(struct work_struct *work)
577 if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING) 318 if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING)
578 goto out; 319 goto out;
579 320
580 send_packet(forw_packet); 321 bat_ogm_emit(forw_packet);
581 322
582 /** 323 /**
583 * we have to have at least one packet in the queue 324 * we have to have at least one packet in the queue
@@ -585,7 +326,7 @@ void send_outstanding_bat_packet(struct work_struct *work)
585 * shutting down 326 * shutting down
586 */ 327 */
587 if (forw_packet->own) 328 if (forw_packet->own)
588 schedule_own_packet(forw_packet->if_incoming); 329 schedule_bat_ogm(forw_packet->if_incoming);
589 330
590out: 331out:
591 /* don't count own packet */ 332 /* don't count own packet */
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 8a22d841b2ea..c8ca3ef7385b 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -24,15 +24,10 @@
24 24
25int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface, 25int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface,
26 const uint8_t *dst_addr); 26 const uint8_t *dst_addr);
27void schedule_own_packet(struct hard_iface *hard_iface); 27void schedule_bat_ogm(struct hard_iface *hard_iface);
28void schedule_forward_packet(struct orig_node *orig_node,
29 const struct ethhdr *ethhdr,
30 struct batman_ogm_packet *batman_ogm_packet,
31 int directlink,
32 struct hard_iface *if_outgoing);
33int add_bcast_packet_to_list(struct bat_priv *bat_priv, 28int add_bcast_packet_to_list(struct bat_priv *bat_priv,
34 const struct sk_buff *skb, unsigned long delay); 29 const struct sk_buff *skb, unsigned long delay);
35void send_outstanding_bat_packet(struct work_struct *work); 30void send_outstanding_bat_ogm_packet(struct work_struct *work);
36void purge_outstanding_packets(struct bat_priv *bat_priv, 31void purge_outstanding_packets(struct bat_priv *bat_priv,
37 const struct hard_iface *hard_iface); 32 const struct hard_iface *hard_iface);
38 33