aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2011-08-03 03:09:30 -0400
committerMarek Lindner <lindner_marek@yahoo.de>2011-09-08 11:44:41 -0400
commitb9dacc521f1cc21f018b27c9f83668258aaec8a2 (patch)
tree23187d4eb263098f2ab4e9fb48f0442a1bfea48d /net/batman-adv
parentd0b9fd89c2e44693e4c696bc1454fbe623d2e261 (diff)
batman-adv: agglomerate all batman iv ogm sending functions in the batman iv file
In the process the batman iv OGM aggregation code could be merged into the batman iv code base which makes the separate aggregation files superfluous. Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
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