aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/Makefile2
-rw-r--r--net/batman-adv/aggregation.c293
-rw-r--r--net/batman-adv/aggregation.h46
-rw-r--r--net/batman-adv/bat_iv_ogm.c1170
-rw-r--r--net/batman-adv/bat_ogm.h35
-rw-r--r--net/batman-adv/bat_sysfs.c2
-rw-r--r--net/batman-adv/bitarray.c6
-rw-r--r--net/batman-adv/gateway_client.c10
-rw-r--r--net/batman-adv/hard-interface.c88
-rw-r--r--net/batman-adv/hard-interface.h1
-rw-r--r--net/batman-adv/hash.h25
-rw-r--r--net/batman-adv/main.c4
-rw-r--r--net/batman-adv/main.h8
-rw-r--r--net/batman-adv/originator.c21
-rw-r--r--net/batman-adv/packet.h19
-rw-r--r--net/batman-adv/routing.c669
-rw-r--r--net/batman-adv/routing.h17
-rw-r--r--net/batman-adv/send.c313
-rw-r--r--net/batman-adv/send.h9
-rw-r--r--net/batman-adv/soft-interface.c36
-rw-r--r--net/batman-adv/translation-table.c206
-rw-r--r--net/batman-adv/translation-table.h21
-rw-r--r--net/batman-adv/types.h5
-rw-r--r--net/batman-adv/unicast.c6
-rw-r--r--net/batman-adv/unicast.h2
-rw-r--r--net/batman-adv/vis.c10
26 files changed, 1585 insertions, 1439 deletions
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 2de93d00631b..ce6861166499 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -19,8 +19,8 @@
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
23batman-adv-y += bat_iv_ogm.o
24batman-adv-y += bat_sysfs.o 24batman-adv-y += bat_sysfs.o
25batman-adv-y += bitarray.o 25batman-adv-y += bitarray.o
26batman-adv-y += gateway_client.o 26batman-adv-y += gateway_client.o
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
deleted file mode 100644
index 69467fe71ff2..000000000000
--- a/net/batman-adv/aggregation.c
+++ /dev/null
@@ -1,293 +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_packet *new_batman_packet,
31 struct bat_priv *bat_priv,
32 int packet_len,
33 unsigned long send_time,
34 bool directlink,
35 const struct hard_iface *if_incoming,
36 const struct forw_packet *forw_packet)
37{
38 struct batman_packet *batman_packet =
39 (struct batman_packet *)forw_packet->skb->data;
40 int aggregated_bytes = forw_packet->packet_len + packet_len;
41 struct hard_iface *primary_if = NULL;
42 bool res = false;
43
44 /**
45 * we can aggregate the current packet to this aggregated packet
46 * if:
47 *
48 * - the send time is within our MAX_AGGREGATION_MS time
49 * - the resulting packet wont be bigger than
50 * MAX_AGGREGATION_BYTES
51 */
52
53 if (time_before(send_time, forw_packet->send_time) &&
54 time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
55 forw_packet->send_time) &&
56 (aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
57
58 /**
59 * check aggregation compatibility
60 * -> direct link packets are broadcasted on
61 * their interface only
62 * -> aggregate packet if the current packet is
63 * a "global" packet as well as the base
64 * packet
65 */
66
67 primary_if = primary_if_get_selected(bat_priv);
68 if (!primary_if)
69 goto out;
70
71 /* packets without direct link flag and high TTL
72 * are flooded through the net */
73 if ((!directlink) &&
74 (!(batman_packet->flags & DIRECTLINK)) &&
75 (batman_packet->ttl != 1) &&
76
77 /* own packets originating non-primary
78 * interfaces leave only that interface */
79 ((!forw_packet->own) ||
80 (forw_packet->if_incoming == primary_if))) {
81 res = true;
82 goto out;
83 }
84
85 /* if the incoming packet is sent via this one
86 * interface only - we still can aggregate */
87 if ((directlink) &&
88 (new_batman_packet->ttl == 1) &&
89 (forw_packet->if_incoming == if_incoming) &&
90
91 /* packets from direct neighbors or
92 * own secondary interface packets
93 * (= secondary interface packets in general) */
94 (batman_packet->flags & DIRECTLINK ||
95 (forw_packet->own &&
96 forw_packet->if_incoming != primary_if))) {
97 res = true;
98 goto out;
99 }
100 }
101
102out:
103 if (primary_if)
104 hardif_free_ref(primary_if);
105 return res;
106}
107
108/* create a new aggregated packet and add this packet to it */
109static void new_aggregated_packet(const unsigned char *packet_buff,
110 int packet_len, unsigned long send_time,
111 bool direct_link,
112 struct hard_iface *if_incoming,
113 int own_packet)
114{
115 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
116 struct forw_packet *forw_packet_aggr;
117 unsigned char *skb_buff;
118
119 if (!atomic_inc_not_zero(&if_incoming->refcount))
120 return;
121
122 /* own packet should always be scheduled */
123 if (!own_packet) {
124 if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
125 bat_dbg(DBG_BATMAN, bat_priv,
126 "batman packet queue full\n");
127 goto out;
128 }
129 }
130
131 forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC);
132 if (!forw_packet_aggr) {
133 if (!own_packet)
134 atomic_inc(&bat_priv->batman_queue_left);
135 goto out;
136 }
137
138 if ((atomic_read(&bat_priv->aggregated_ogms)) &&
139 (packet_len < MAX_AGGREGATION_BYTES))
140 forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES +
141 sizeof(struct ethhdr));
142 else
143 forw_packet_aggr->skb = dev_alloc_skb(packet_len +
144 sizeof(struct ethhdr));
145
146 if (!forw_packet_aggr->skb) {
147 if (!own_packet)
148 atomic_inc(&bat_priv->batman_queue_left);
149 kfree(forw_packet_aggr);
150 goto out;
151 }
152 skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
153
154 INIT_HLIST_NODE(&forw_packet_aggr->list);
155
156 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
157 forw_packet_aggr->packet_len = packet_len;
158 memcpy(skb_buff, packet_buff, packet_len);
159
160 forw_packet_aggr->own = own_packet;
161 forw_packet_aggr->if_incoming = if_incoming;
162 forw_packet_aggr->num_packets = 0;
163 forw_packet_aggr->direct_link_flags = NO_FLAGS;
164 forw_packet_aggr->send_time = send_time;
165
166 /* save packet direct link flag status */
167 if (direct_link)
168 forw_packet_aggr->direct_link_flags |= 1;
169
170 /* add new packet to packet list */
171 spin_lock_bh(&bat_priv->forw_bat_list_lock);
172 hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
173 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
174
175 /* start timer for this packet */
176 INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
177 send_outstanding_bat_packet);
178 queue_delayed_work(bat_event_workqueue,
179 &forw_packet_aggr->delayed_work,
180 send_time - jiffies);
181
182 return;
183out:
184 hardif_free_ref(if_incoming);
185}
186
187/* aggregate a new packet into the existing aggregation */
188static void aggregate(struct forw_packet *forw_packet_aggr,
189 const unsigned char *packet_buff, int packet_len,
190 bool direct_link)
191{
192 unsigned char *skb_buff;
193
194 skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
195 memcpy(skb_buff, packet_buff, packet_len);
196 forw_packet_aggr->packet_len += packet_len;
197 forw_packet_aggr->num_packets++;
198
199 /* save packet direct link flag status */
200 if (direct_link)
201 forw_packet_aggr->direct_link_flags |=
202 (1 << forw_packet_aggr->num_packets);
203}
204
205void add_bat_packet_to_list(struct bat_priv *bat_priv,
206 unsigned char *packet_buff, int packet_len,
207 struct hard_iface *if_incoming, int own_packet,
208 unsigned long send_time)
209{
210 /**
211 * _aggr -> pointer to the packet we want to aggregate with
212 * _pos -> pointer to the position in the queue
213 */
214 struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL;
215 struct hlist_node *tmp_node;
216 struct batman_packet *batman_packet =
217 (struct batman_packet *)packet_buff;
218 bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0;
219
220 /* find position for the packet in the forward queue */
221 spin_lock_bh(&bat_priv->forw_bat_list_lock);
222 /* own packets are not to be aggregated */
223 if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) {
224 hlist_for_each_entry(forw_packet_pos, tmp_node,
225 &bat_priv->forw_bat_list, list) {
226 if (can_aggregate_with(batman_packet,
227 bat_priv,
228 packet_len,
229 send_time,
230 direct_link,
231 if_incoming,
232 forw_packet_pos)) {
233 forw_packet_aggr = forw_packet_pos;
234 break;
235 }
236 }
237 }
238
239 /* nothing to aggregate with - either aggregation disabled or no
240 * suitable aggregation packet found */
241 if (!forw_packet_aggr) {
242 /* the following section can run without the lock */
243 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
244
245 /**
246 * if we could not aggregate this packet with one of the others
247 * we hold it back for a while, so that it might be aggregated
248 * later on
249 */
250 if ((!own_packet) &&
251 (atomic_read(&bat_priv->aggregated_ogms)))
252 send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
253
254 new_aggregated_packet(packet_buff, packet_len,
255 send_time, direct_link,
256 if_incoming, own_packet);
257 } else {
258 aggregate(forw_packet_aggr,
259 packet_buff, packet_len,
260 direct_link);
261 spin_unlock_bh(&bat_priv->forw_bat_list_lock);
262 }
263}
264
265/* unpack the aggregated packets and process them one by one */
266void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
267 unsigned char *packet_buff, int packet_len,
268 struct hard_iface *if_incoming)
269{
270 struct batman_packet *batman_packet;
271 int buff_pos = 0;
272 unsigned char *tt_buff;
273
274 batman_packet = (struct batman_packet *)packet_buff;
275
276 do {
277 /* network to host order for our 32bit seqno and the
278 orig_interval */
279 batman_packet->seqno = ntohl(batman_packet->seqno);
280 batman_packet->tt_crc = ntohs(batman_packet->tt_crc);
281
282 tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
283
284 receive_bat_packet(ethhdr, batman_packet, tt_buff, if_incoming);
285
286 buff_pos += BAT_PACKET_LEN +
287 tt_len(batman_packet->tt_num_changes);
288
289 batman_packet = (struct batman_packet *)
290 (packet_buff + buff_pos);
291 } while (aggregated_packet(buff_pos, packet_len,
292 batman_packet->tt_num_changes));
293}
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
deleted file mode 100644
index 216337bb841f..000000000000
--- a/net/batman-adv/aggregation.h
+++ /dev/null
@@ -1,46 +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 + BAT_PACKET_LEN + (tt_num_changes *
32 sizeof(struct tt_change));
33
34 return (next_buff_pos <= packet_len) &&
35 (next_buff_pos <= MAX_AGGREGATION_BYTES);
36}
37
38void add_bat_packet_to_list(struct bat_priv *bat_priv,
39 unsigned char *packet_buff, int packet_len,
40 struct hard_iface *if_incoming, int own_packet,
41 unsigned long send_time);
42void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
43 unsigned char *packet_buff, int packet_len,
44 struct hard_iface *if_incoming);
45
46#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
new file mode 100644
index 000000000000..3512e251545b
--- /dev/null
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -0,0 +1,1170 @@
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 "bat_ogm.h"
24#include "translation-table.h"
25#include "ring_buffer.h"
26#include "originator.h"
27#include "routing.h"
28#include "gateway_common.h"
29#include "gateway_client.h"
30#include "hard-interface.h"
31#include "send.h"
32
33void bat_ogm_init(struct hard_iface *hard_iface)
34{
35 struct batman_ogm_packet *batman_ogm_packet;
36
37 hard_iface->packet_len = BATMAN_OGM_LEN;
38 hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
39
40 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
41 batman_ogm_packet->packet_type = BAT_OGM;
42 batman_ogm_packet->version = COMPAT_VERSION;
43 batman_ogm_packet->flags = NO_FLAGS;
44 batman_ogm_packet->ttl = 2;
45 batman_ogm_packet->tq = TQ_MAX_VALUE;
46 batman_ogm_packet->tt_num_changes = 0;
47 batman_ogm_packet->ttvn = 0;
48}
49
50void bat_ogm_init_primary(struct hard_iface *hard_iface)
51{
52 struct batman_ogm_packet *batman_ogm_packet;
53
54 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
55 batman_ogm_packet->flags = PRIMARIES_FIRST_HOP;
56 batman_ogm_packet->ttl = TTL;
57}
58
59void bat_ogm_update_mac(struct hard_iface *hard_iface)
60{
61 struct batman_ogm_packet *batman_ogm_packet;
62
63 batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
64 memcpy(batman_ogm_packet->orig,
65 hard_iface->net_dev->dev_addr, ETH_ALEN);
66 memcpy(batman_ogm_packet->prev_sender,
67 hard_iface->net_dev->dev_addr, ETH_ALEN);
68}
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
91/* is there another aggregated packet here? */
92static int bat_ogm_aggr_packet(int buff_pos, int packet_len,
93 int tt_num_changes)
94{
95 int next_buff_pos = buff_pos + BATMAN_OGM_LEN + tt_len(tt_num_changes);
96
97 return (next_buff_pos <= packet_len) &&
98 (next_buff_pos <= MAX_AGGREGATION_BYTES);
99}
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
575static void bat_ogm_orig_update(struct bat_priv *bat_priv,
576 struct orig_node *orig_node,
577 const struct ethhdr *ethhdr,
578 const struct batman_ogm_packet
579 *batman_ogm_packet,
580 struct hard_iface *if_incoming,
581 const unsigned char *tt_buff, int is_duplicate)
582{
583 struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
584 struct neigh_node *router = NULL;
585 struct orig_node *orig_node_tmp;
586 struct hlist_node *node;
587 uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
588
589 bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
590 "Searching and updating originator entry of received packet\n");
591
592 rcu_read_lock();
593 hlist_for_each_entry_rcu(tmp_neigh_node, node,
594 &orig_node->neigh_list, list) {
595 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
596 (tmp_neigh_node->if_incoming == if_incoming) &&
597 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
598 if (neigh_node)
599 neigh_node_free_ref(neigh_node);
600 neigh_node = tmp_neigh_node;
601 continue;
602 }
603
604 if (is_duplicate)
605 continue;
606
607 spin_lock_bh(&tmp_neigh_node->tq_lock);
608 ring_buffer_set(tmp_neigh_node->tq_recv,
609 &tmp_neigh_node->tq_index, 0);
610 tmp_neigh_node->tq_avg =
611 ring_buffer_avg(tmp_neigh_node->tq_recv);
612 spin_unlock_bh(&tmp_neigh_node->tq_lock);
613 }
614
615 if (!neigh_node) {
616 struct orig_node *orig_tmp;
617
618 orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
619 if (!orig_tmp)
620 goto unlock;
621
622 neigh_node = create_neighbor(orig_node, orig_tmp,
623 ethhdr->h_source, if_incoming);
624
625 orig_node_free_ref(orig_tmp);
626 if (!neigh_node)
627 goto unlock;
628 } else
629 bat_dbg(DBG_BATMAN, bat_priv,
630 "Updating existing last-hop neighbor of originator\n");
631
632 rcu_read_unlock();
633
634 orig_node->flags = batman_ogm_packet->flags;
635 neigh_node->last_valid = jiffies;
636
637 spin_lock_bh(&neigh_node->tq_lock);
638 ring_buffer_set(neigh_node->tq_recv,
639 &neigh_node->tq_index,
640 batman_ogm_packet->tq);
641 neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
642 spin_unlock_bh(&neigh_node->tq_lock);
643
644 if (!is_duplicate) {
645 orig_node->last_ttl = batman_ogm_packet->ttl;
646 neigh_node->last_ttl = batman_ogm_packet->ttl;
647 }
648
649 bonding_candidate_add(orig_node, neigh_node);
650
651 /* if this neighbor already is our next hop there is nothing
652 * to change */
653 router = orig_node_get_router(orig_node);
654 if (router == neigh_node)
655 goto update_tt;
656
657 /* if this neighbor does not offer a better TQ we won't consider it */
658 if (router && (router->tq_avg > neigh_node->tq_avg))
659 goto update_tt;
660
661 /* if the TQ is the same and the link not more symmetric we
662 * won't consider it either */
663 if (router && (neigh_node->tq_avg == router->tq_avg)) {
664 orig_node_tmp = router->orig_node;
665 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
666 bcast_own_sum_orig =
667 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
668 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
669
670 orig_node_tmp = neigh_node->orig_node;
671 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
672 bcast_own_sum_neigh =
673 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
674 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
675
676 if (bcast_own_sum_orig >= bcast_own_sum_neigh)
677 goto update_tt;
678 }
679
680 update_route(bat_priv, orig_node, neigh_node);
681
682update_tt:
683 /* I have to check for transtable changes only if the OGM has been
684 * sent through a primary interface */
685 if (((batman_ogm_packet->orig != ethhdr->h_source) &&
686 (batman_ogm_packet->ttl > 2)) ||
687 (batman_ogm_packet->flags & PRIMARIES_FIRST_HOP))
688 tt_update_orig(bat_priv, orig_node, tt_buff,
689 batman_ogm_packet->tt_num_changes,
690 batman_ogm_packet->ttvn,
691 batman_ogm_packet->tt_crc);
692
693 if (orig_node->gw_flags != batman_ogm_packet->gw_flags)
694 gw_node_update(bat_priv, orig_node,
695 batman_ogm_packet->gw_flags);
696
697 orig_node->gw_flags = batman_ogm_packet->gw_flags;
698
699 /* restart gateway selection if fast or late switching was enabled */
700 if ((orig_node->gw_flags) &&
701 (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
702 (atomic_read(&bat_priv->gw_sel_class) > 2))
703 gw_check_election(bat_priv, orig_node);
704
705 goto out;
706
707unlock:
708 rcu_read_unlock();
709out:
710 if (neigh_node)
711 neigh_node_free_ref(neigh_node);
712 if (router)
713 neigh_node_free_ref(router);
714}
715
716static int bat_ogm_calc_tq(struct orig_node *orig_node,
717 struct orig_node *orig_neigh_node,
718 struct batman_ogm_packet *batman_ogm_packet,
719 struct hard_iface *if_incoming)
720{
721 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
722 struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
723 struct hlist_node *node;
724 uint8_t total_count;
725 uint8_t orig_eq_count, neigh_rq_count, tq_own;
726 int tq_asym_penalty, ret = 0;
727
728 /* find corresponding one hop neighbor */
729 rcu_read_lock();
730 hlist_for_each_entry_rcu(tmp_neigh_node, node,
731 &orig_neigh_node->neigh_list, list) {
732
733 if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig))
734 continue;
735
736 if (tmp_neigh_node->if_incoming != if_incoming)
737 continue;
738
739 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
740 continue;
741
742 neigh_node = tmp_neigh_node;
743 break;
744 }
745 rcu_read_unlock();
746
747 if (!neigh_node)
748 neigh_node = create_neighbor(orig_neigh_node,
749 orig_neigh_node,
750 orig_neigh_node->orig,
751 if_incoming);
752
753 if (!neigh_node)
754 goto out;
755
756 /* if orig_node is direct neighbor update neigh_node last_valid */
757 if (orig_node == orig_neigh_node)
758 neigh_node->last_valid = jiffies;
759
760 orig_node->last_valid = jiffies;
761
762 /* find packet count of corresponding one hop neighbor */
763 spin_lock_bh(&orig_node->ogm_cnt_lock);
764 orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
765 neigh_rq_count = neigh_node->real_packet_count;
766 spin_unlock_bh(&orig_node->ogm_cnt_lock);
767
768 /* pay attention to not get a value bigger than 100 % */
769 total_count = (orig_eq_count > neigh_rq_count ?
770 neigh_rq_count : orig_eq_count);
771
772 /* if we have too few packets (too less data) we set tq_own to zero */
773 /* if we receive too few packets it is not considered bidirectional */
774 if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
775 (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
776 tq_own = 0;
777 else
778 /* neigh_node->real_packet_count is never zero as we
779 * only purge old information when getting new
780 * information */
781 tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count;
782
783 /*
784 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
785 * affect the nearly-symmetric links only a little, but
786 * punishes asymmetric links more. This will give a value
787 * between 0 and TQ_MAX_VALUE
788 */
789 tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
790 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
791 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
792 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) /
793 (TQ_LOCAL_WINDOW_SIZE *
794 TQ_LOCAL_WINDOW_SIZE *
795 TQ_LOCAL_WINDOW_SIZE);
796
797 batman_ogm_packet->tq = ((batman_ogm_packet->tq * tq_own
798 * tq_asym_penalty) /
799 (TQ_MAX_VALUE * TQ_MAX_VALUE));
800
801 bat_dbg(DBG_BATMAN, bat_priv,
802 "bidirectional: "
803 "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
804 "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
805 "total tq: %3i\n",
806 orig_node->orig, orig_neigh_node->orig, total_count,
807 neigh_rq_count, tq_own, tq_asym_penalty, batman_ogm_packet->tq);
808
809 /* if link has the minimum required transmission quality
810 * consider it bidirectional */
811 if (batman_ogm_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
812 ret = 1;
813
814out:
815 if (neigh_node)
816 neigh_node_free_ref(neigh_node);
817 return ret;
818}
819
820/* processes a batman packet for all interfaces, adjusts the sequence number and
821 * finds out whether it is a duplicate.
822 * returns:
823 * 1 the packet is a duplicate
824 * 0 the packet has not yet been received
825 * -1 the packet is old and has been received while the seqno window
826 * was protected. Caller should drop it.
827 */
828static int bat_ogm_update_seqnos(const struct ethhdr *ethhdr,
829 const struct batman_ogm_packet
830 *batman_ogm_packet,
831 const struct hard_iface *if_incoming)
832{
833 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
834 struct orig_node *orig_node;
835 struct neigh_node *tmp_neigh_node;
836 struct hlist_node *node;
837 int is_duplicate = 0;
838 int32_t seq_diff;
839 int need_update = 0;
840 int set_mark, ret = -1;
841
842 orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig);
843 if (!orig_node)
844 return 0;
845
846 spin_lock_bh(&orig_node->ogm_cnt_lock);
847 seq_diff = batman_ogm_packet->seqno - orig_node->last_real_seqno;
848
849 /* signalize caller that the packet is to be dropped. */
850 if (window_protected(bat_priv, seq_diff,
851 &orig_node->batman_seqno_reset))
852 goto out;
853
854 rcu_read_lock();
855 hlist_for_each_entry_rcu(tmp_neigh_node, node,
856 &orig_node->neigh_list, list) {
857
858 is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
859 orig_node->last_real_seqno,
860 batman_ogm_packet->seqno);
861
862 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
863 (tmp_neigh_node->if_incoming == if_incoming))
864 set_mark = 1;
865 else
866 set_mark = 0;
867
868 /* if the window moved, set the update flag. */
869 need_update |= bit_get_packet(bat_priv,
870 tmp_neigh_node->real_bits,
871 seq_diff, set_mark);
872
873 tmp_neigh_node->real_packet_count =
874 bit_packet_count(tmp_neigh_node->real_bits);
875 }
876 rcu_read_unlock();
877
878 if (need_update) {
879 bat_dbg(DBG_BATMAN, bat_priv,
880 "updating last_seqno: old %d, new %d\n",
881 orig_node->last_real_seqno, batman_ogm_packet->seqno);
882 orig_node->last_real_seqno = batman_ogm_packet->seqno;
883 }
884
885 ret = is_duplicate;
886
887out:
888 spin_unlock_bh(&orig_node->ogm_cnt_lock);
889 orig_node_free_ref(orig_node);
890 return ret;
891}
892
893static void bat_ogm_process(const struct ethhdr *ethhdr,
894 struct batman_ogm_packet *batman_ogm_packet,
895 const unsigned char *tt_buff,
896 struct hard_iface *if_incoming)
897{
898 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
899 struct hard_iface *hard_iface;
900 struct orig_node *orig_neigh_node, *orig_node;
901 struct neigh_node *router = NULL, *router_router = NULL;
902 struct neigh_node *orig_neigh_router = NULL;
903 int has_directlink_flag;
904 int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
905 int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
906 int is_duplicate;
907 uint32_t if_incoming_seqno;
908
909 /* Silently drop when the batman packet is actually not a
910 * correct packet.
911 *
912 * This might happen if a packet is padded (e.g. Ethernet has a
913 * minimum frame length of 64 byte) and the aggregation interprets
914 * it as an additional length.
915 *
916 * TODO: A more sane solution would be to have a bit in the
917 * batman_ogm_packet to detect whether the packet is the last
918 * packet in an aggregation. Here we expect that the padding
919 * is always zero (or not 0x01)
920 */
921 if (batman_ogm_packet->packet_type != BAT_OGM)
922 return;
923
924 /* could be changed by schedule_own_packet() */
925 if_incoming_seqno = atomic_read(&if_incoming->seqno);
926
927 has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
928
929 is_single_hop_neigh = (compare_eth(ethhdr->h_source,
930 batman_ogm_packet->orig) ? 1 : 0);
931
932 bat_dbg(DBG_BATMAN, bat_priv,
933 "Received BATMAN packet via NB: %pM, IF: %s [%pM] "
934 "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, "
935 "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
936 ethhdr->h_source, if_incoming->net_dev->name,
937 if_incoming->net_dev->dev_addr, batman_ogm_packet->orig,
938 batman_ogm_packet->prev_sender, batman_ogm_packet->seqno,
939 batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc,
940 batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq,
941 batman_ogm_packet->ttl, batman_ogm_packet->version,
942 has_directlink_flag);
943
944 rcu_read_lock();
945 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
946 if (hard_iface->if_status != IF_ACTIVE)
947 continue;
948
949 if (hard_iface->soft_iface != if_incoming->soft_iface)
950 continue;
951
952 if (compare_eth(ethhdr->h_source,
953 hard_iface->net_dev->dev_addr))
954 is_my_addr = 1;
955
956 if (compare_eth(batman_ogm_packet->orig,
957 hard_iface->net_dev->dev_addr))
958 is_my_orig = 1;
959
960 if (compare_eth(batman_ogm_packet->prev_sender,
961 hard_iface->net_dev->dev_addr))
962 is_my_oldorig = 1;
963
964 if (is_broadcast_ether_addr(ethhdr->h_source))
965 is_broadcast = 1;
966 }
967 rcu_read_unlock();
968
969 if (batman_ogm_packet->version != COMPAT_VERSION) {
970 bat_dbg(DBG_BATMAN, bat_priv,
971 "Drop packet: incompatible batman version (%i)\n",
972 batman_ogm_packet->version);
973 return;
974 }
975
976 if (is_my_addr) {
977 bat_dbg(DBG_BATMAN, bat_priv,
978 "Drop packet: received my own broadcast (sender: %pM"
979 ")\n",
980 ethhdr->h_source);
981 return;
982 }
983
984 if (is_broadcast) {
985 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
986 "ignoring all packets with broadcast source addr (sender: %pM"
987 ")\n", ethhdr->h_source);
988 return;
989 }
990
991 if (is_my_orig) {
992 unsigned long *word;
993 int offset;
994
995 orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
996 if (!orig_neigh_node)
997 return;
998
999 /* neighbor has to indicate direct link and it has to
1000 * come via the corresponding interface */
1001 /* save packet seqno for bidirectional check */
1002 if (has_directlink_flag &&
1003 compare_eth(if_incoming->net_dev->dev_addr,
1004 batman_ogm_packet->orig)) {
1005 offset = if_incoming->if_num * NUM_WORDS;
1006
1007 spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
1008 word = &(orig_neigh_node->bcast_own[offset]);
1009 bit_mark(word,
1010 if_incoming_seqno -
1011 batman_ogm_packet->seqno - 2);
1012 orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
1013 bit_packet_count(word);
1014 spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
1015 }
1016
1017 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
1018 "originator packet from myself (via neighbor)\n");
1019 orig_node_free_ref(orig_neigh_node);
1020 return;
1021 }
1022
1023 if (is_my_oldorig) {
1024 bat_dbg(DBG_BATMAN, bat_priv,
1025 "Drop packet: ignoring all rebroadcast echos (sender: "
1026 "%pM)\n", ethhdr->h_source);
1027 return;
1028 }
1029
1030 orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig);
1031 if (!orig_node)
1032 return;
1033
1034 is_duplicate = bat_ogm_update_seqnos(ethhdr, batman_ogm_packet,
1035 if_incoming);
1036
1037 if (is_duplicate == -1) {
1038 bat_dbg(DBG_BATMAN, bat_priv,
1039 "Drop packet: packet within seqno protection time "
1040 "(sender: %pM)\n", ethhdr->h_source);
1041 goto out;
1042 }
1043
1044 if (batman_ogm_packet->tq == 0) {
1045 bat_dbg(DBG_BATMAN, bat_priv,
1046 "Drop packet: originator packet with tq equal 0\n");
1047 goto out;
1048 }
1049
1050 router = orig_node_get_router(orig_node);
1051 if (router)
1052 router_router = orig_node_get_router(router->orig_node);
1053
1054 /* avoid temporary routing loops */
1055 if (router && router_router &&
1056 (compare_eth(router->addr, batman_ogm_packet->prev_sender)) &&
1057 !(compare_eth(batman_ogm_packet->orig,
1058 batman_ogm_packet->prev_sender)) &&
1059 (compare_eth(router->addr, router_router->addr))) {
1060 bat_dbg(DBG_BATMAN, bat_priv,
1061 "Drop packet: ignoring all rebroadcast packets that "
1062 "may make me loop (sender: %pM)\n", ethhdr->h_source);
1063 goto out;
1064 }
1065
1066 /* if sender is a direct neighbor the sender mac equals
1067 * originator mac */
1068 orig_neigh_node = (is_single_hop_neigh ?
1069 orig_node :
1070 get_orig_node(bat_priv, ethhdr->h_source));
1071 if (!orig_neigh_node)
1072 goto out;
1073
1074 orig_neigh_router = orig_node_get_router(orig_neigh_node);
1075
1076 /* drop packet if sender is not a direct neighbor and if we
1077 * don't route towards it */
1078 if (!is_single_hop_neigh && (!orig_neigh_router)) {
1079 bat_dbg(DBG_BATMAN, bat_priv,
1080 "Drop packet: OGM via unknown neighbor!\n");
1081 goto out_neigh;
1082 }
1083
1084 is_bidirectional = bat_ogm_calc_tq(orig_node, orig_neigh_node,
1085 batman_ogm_packet, if_incoming);
1086
1087 bonding_save_primary(orig_node, orig_neigh_node, batman_ogm_packet);
1088
1089 /* update ranking if it is not a duplicate or has the same
1090 * seqno and similar ttl as the non-duplicate */
1091 if (is_bidirectional &&
1092 (!is_duplicate ||
1093 ((orig_node->last_real_seqno == batman_ogm_packet->seqno) &&
1094 (orig_node->last_ttl - 3 <= batman_ogm_packet->ttl))))
1095 bat_ogm_orig_update(bat_priv, orig_node, ethhdr,
1096 batman_ogm_packet, if_incoming,
1097 tt_buff, is_duplicate);
1098
1099 /* is single hop (direct) neighbor */
1100 if (is_single_hop_neigh) {
1101
1102 /* mark direct link on incoming interface */
1103 bat_ogm_forward(orig_node, ethhdr, batman_ogm_packet,
1104 1, if_incoming);
1105
1106 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
1107 "rebroadcast neighbor packet with direct link flag\n");
1108 goto out_neigh;
1109 }
1110
1111 /* multihop originator */
1112 if (!is_bidirectional) {
1113 bat_dbg(DBG_BATMAN, bat_priv,
1114 "Drop packet: not received via bidirectional link\n");
1115 goto out_neigh;
1116 }
1117
1118 if (is_duplicate) {
1119 bat_dbg(DBG_BATMAN, bat_priv,
1120 "Drop packet: duplicate packet received\n");
1121 goto out_neigh;
1122 }
1123
1124 bat_dbg(DBG_BATMAN, bat_priv,
1125 "Forwarding packet: rebroadcast originator packet\n");
1126 bat_ogm_forward(orig_node, ethhdr, batman_ogm_packet, 0, if_incoming);
1127
1128out_neigh:
1129 if ((orig_neigh_node) && (!is_single_hop_neigh))
1130 orig_node_free_ref(orig_neigh_node);
1131out:
1132 if (router)
1133 neigh_node_free_ref(router);
1134 if (router_router)
1135 neigh_node_free_ref(router_router);
1136 if (orig_neigh_router)
1137 neigh_node_free_ref(orig_neigh_router);
1138
1139 orig_node_free_ref(orig_node);
1140}
1141
1142void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff,
1143 int packet_len, struct hard_iface *if_incoming)
1144{
1145 struct batman_ogm_packet *batman_ogm_packet;
1146 int buff_pos = 0;
1147 unsigned char *tt_buff;
1148
1149 batman_ogm_packet = (struct batman_ogm_packet *)packet_buff;
1150
1151 /* unpack the aggregated packets and process them one by one */
1152 do {
1153 /* network to host order for our 32bit seqno and the
1154 orig_interval */
1155 batman_ogm_packet->seqno = ntohl(batman_ogm_packet->seqno);
1156 batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc);
1157
1158 tt_buff = packet_buff + buff_pos + BATMAN_OGM_LEN;
1159
1160 bat_ogm_process(ethhdr, batman_ogm_packet,
1161 tt_buff, if_incoming);
1162
1163 buff_pos += BATMAN_OGM_LEN +
1164 tt_len(batman_ogm_packet->tt_num_changes);
1165
1166 batman_ogm_packet = (struct batman_ogm_packet *)
1167 (packet_buff + buff_pos);
1168 } while (bat_ogm_aggr_packet(buff_pos, packet_len,
1169 batman_ogm_packet->tt_num_changes));
1170}
diff --git a/net/batman-adv/bat_ogm.h b/net/batman-adv/bat_ogm.h
new file mode 100644
index 000000000000..69329c107e28
--- /dev/null
+++ b/net/batman-adv/bat_ogm.h
@@ -0,0 +1,35 @@
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_OGM_H_
23#define _NET_BATMAN_ADV_OGM_H_
24
25#include "main.h"
26
27void bat_ogm_init(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);
30void bat_ogm_schedule(struct hard_iface *hard_iface, int tt_num_changes);
31void bat_ogm_emit(struct forw_packet *forw_packet);
32void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff,
33 int packet_len, struct hard_iface *if_incoming);
34
35#endif /* _NET_BATMAN_ADV_OGM_H_ */
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index cd15deba60a1..b8a7414c3571 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -380,6 +380,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
380BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); 380BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
381BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); 381BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
382BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); 382BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
383BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
383static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); 384static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
384static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); 385static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
385BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); 386BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
@@ -396,6 +397,7 @@ static struct bat_attribute *mesh_attrs[] = {
396 &bat_attr_aggregated_ogms, 397 &bat_attr_aggregated_ogms,
397 &bat_attr_bonding, 398 &bat_attr_bonding,
398 &bat_attr_fragmentation, 399 &bat_attr_fragmentation,
400 &bat_attr_ap_isolation,
399 &bat_attr_vis_mode, 401 &bat_attr_vis_mode,
400 &bat_attr_gw_mode, 402 &bat_attr_gw_mode,
401 &bat_attr_orig_interval, 403 &bat_attr_orig_interval,
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index c1f4bfc09cc3..0be9ff346fa0 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -97,12 +97,12 @@ static void bit_shift(unsigned long *seq_bits, int32_t n)
97 (seq_bits[i - word_num - 1] >> 97 (seq_bits[i - word_num - 1] >>
98 (WORD_BIT_SIZE-word_offset)); 98 (WORD_BIT_SIZE-word_offset));
99 /* and the upper part of the right half and shift it left to 99 /* and the upper part of the right half and shift it left to
100 * it's position */ 100 * its position */
101 /* for our example that would be: word[0] = 9800 + 0076 = 101 /* for our example that would be: word[0] = 9800 + 0076 =
102 * 9876 */ 102 * 9876 */
103 } 103 }
104 /* now for our last word, i==word_num, we only have the it's "left" 104 /* now for our last word, i==word_num, we only have its "left" half.
105 * half. that's the 1000 word in our example.*/ 105 * that's the 1000 word in our example.*/
106 106
107 seq_bits[i] = (seq_bits[i - word_num] << word_offset); 107 seq_bits[i] = (seq_bits[i - word_num] << word_offset);
108 108
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 056180ef9e1a..619fb73b3b76 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -532,14 +532,14 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
532 pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1; 532 pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
533 533
534 /* Access the dhcp option lists. Each entry is made up by: 534 /* Access the dhcp option lists. Each entry is made up by:
535 * - octect 1: option type 535 * - octet 1: option type
536 * - octect 2: option data len (only if type != 255 and 0) 536 * - octet 2: option data len (only if type != 255 and 0)
537 * - octect 3: option data */ 537 * - octet 3: option data */
538 while (*p != 255 && !ret) { 538 while (*p != 255 && !ret) {
539 /* p now points to the first octect: option type */ 539 /* p now points to the first octet: option type */
540 if (*p == 53) { 540 if (*p == 53) {
541 /* type 53 is the message type option. 541 /* type 53 is the message type option.
542 * Jump the len octect and go to the data octect */ 542 * Jump the len octet and go to the data octet */
543 if (pkt_len < 2) 543 if (pkt_len < 2)
544 goto out; 544 goto out;
545 p += 2; 545 p += 2;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index db7aacf1e095..7704df468e0b 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -28,6 +28,7 @@
28#include "bat_sysfs.h" 28#include "bat_sysfs.h"
29#include "originator.h" 29#include "originator.h"
30#include "hash.h" 30#include "hash.h"
31#include "bat_ogm.h"
31 32
32#include <linux/if_arp.h> 33#include <linux/if_arp.h>
33 34
@@ -131,7 +132,6 @@ static void primary_if_select(struct bat_priv *bat_priv,
131 struct hard_iface *new_hard_iface) 132 struct hard_iface *new_hard_iface)
132{ 133{
133 struct hard_iface *curr_hard_iface; 134 struct hard_iface *curr_hard_iface;
134 struct batman_packet *batman_packet;
135 135
136 ASSERT_RTNL(); 136 ASSERT_RTNL();
137 137
@@ -147,10 +147,7 @@ static void primary_if_select(struct bat_priv *bat_priv,
147 if (!new_hard_iface) 147 if (!new_hard_iface)
148 return; 148 return;
149 149
150 batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); 150 bat_ogm_init_primary(new_hard_iface);
151 batman_packet->flags = PRIMARIES_FIRST_HOP;
152 batman_packet->ttl = TTL;
153
154 primary_if_update_addr(bat_priv); 151 primary_if_update_addr(bat_priv);
155} 152}
156 153
@@ -162,14 +159,6 @@ static bool hardif_is_iface_up(const struct hard_iface *hard_iface)
162 return false; 159 return false;
163} 160}
164 161
165static void update_mac_addresses(struct hard_iface *hard_iface)
166{
167 memcpy(((struct batman_packet *)(hard_iface->packet_buff))->orig,
168 hard_iface->net_dev->dev_addr, ETH_ALEN);
169 memcpy(((struct batman_packet *)(hard_iface->packet_buff))->prev_sender,
170 hard_iface->net_dev->dev_addr, ETH_ALEN);
171}
172
173static void check_known_mac_addr(const struct net_device *net_dev) 162static void check_known_mac_addr(const struct net_device *net_dev)
174{ 163{
175 const struct hard_iface *hard_iface; 164 const struct hard_iface *hard_iface;
@@ -244,12 +233,12 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
244 233
245 bat_priv = netdev_priv(hard_iface->soft_iface); 234 bat_priv = netdev_priv(hard_iface->soft_iface);
246 235
247 update_mac_addresses(hard_iface); 236 bat_ogm_update_mac(hard_iface);
248 hard_iface->if_status = IF_TO_BE_ACTIVATED; 237 hard_iface->if_status = IF_TO_BE_ACTIVATED;
249 238
250 /** 239 /**
251 * the first active interface becomes our primary interface or 240 * the first active interface becomes our primary interface or
252 * the next active interface after the old primay interface was removed 241 * the next active interface after the old primary interface was removed
253 */ 242 */
254 primary_if = primary_if_get_selected(bat_priv); 243 primary_if = primary_if_get_selected(bat_priv);
255 if (!primary_if) 244 if (!primary_if)
@@ -283,7 +272,6 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
283 const char *iface_name) 272 const char *iface_name)
284{ 273{
285 struct bat_priv *bat_priv; 274 struct bat_priv *bat_priv;
286 struct batman_packet *batman_packet;
287 struct net_device *soft_iface; 275 struct net_device *soft_iface;
288 int ret; 276 int ret;
289 277
@@ -318,8 +306,8 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
318 306
319 hard_iface->soft_iface = soft_iface; 307 hard_iface->soft_iface = soft_iface;
320 bat_priv = netdev_priv(hard_iface->soft_iface); 308 bat_priv = netdev_priv(hard_iface->soft_iface);
321 hard_iface->packet_len = BAT_PACKET_LEN; 309
322 hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); 310 bat_ogm_init(hard_iface);
323 311
324 if (!hard_iface->packet_buff) { 312 if (!hard_iface->packet_buff) {
325 bat_err(hard_iface->soft_iface, "Can't add interface packet " 313 bat_err(hard_iface->soft_iface, "Can't add interface packet "
@@ -328,15 +316,6 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
328 goto err; 316 goto err;
329 } 317 }
330 318
331 batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
332 batman_packet->packet_type = BAT_PACKET;
333 batman_packet->version = COMPAT_VERSION;
334 batman_packet->flags = NO_FLAGS;
335 batman_packet->ttl = 2;
336 batman_packet->tq = TQ_MAX_VALUE;
337 batman_packet->tt_num_changes = 0;
338 batman_packet->ttvn = 0;
339
340 hard_iface->if_num = bat_priv->num_ifaces; 319 hard_iface->if_num = bat_priv->num_ifaces;
341 bat_priv->num_ifaces++; 320 bat_priv->num_ifaces++;
342 hard_iface->if_status = IF_INACTIVE; 321 hard_iface->if_status = IF_INACTIVE;
@@ -381,7 +360,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
381 hard_iface->net_dev->name); 360 hard_iface->net_dev->name);
382 361
383 /* begin scheduling originator messages on that interface */ 362 /* begin scheduling originator messages on that interface */
384 schedule_own_packet(hard_iface); 363 schedule_bat_ogm(hard_iface);
385 364
386out: 365out:
387 return 0; 366 return 0;
@@ -455,11 +434,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
455 dev_hold(net_dev); 434 dev_hold(net_dev);
456 435
457 hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC); 436 hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC);
458 if (!hard_iface) { 437 if (!hard_iface)
459 pr_err("Can't add interface (%s): out of memory\n",
460 net_dev->name);
461 goto release_dev; 438 goto release_dev;
462 }
463 439
464 ret = sysfs_add_hardif(&hard_iface->hardif_obj, net_dev); 440 ret = sysfs_add_hardif(&hard_iface->hardif_obj, net_dev);
465 if (ret) 441 if (ret)
@@ -551,7 +527,7 @@ static int hard_if_event(struct notifier_block *this,
551 goto hardif_put; 527 goto hardif_put;
552 528
553 check_known_mac_addr(hard_iface->net_dev); 529 check_known_mac_addr(hard_iface->net_dev);
554 update_mac_addresses(hard_iface); 530 bat_ogm_update_mac(hard_iface);
555 531
556 bat_priv = netdev_priv(hard_iface->soft_iface); 532 bat_priv = netdev_priv(hard_iface->soft_iface);
557 primary_if = primary_if_get_selected(bat_priv); 533 primary_if = primary_if_get_selected(bat_priv);
@@ -573,14 +549,14 @@ out:
573 return NOTIFY_DONE; 549 return NOTIFY_DONE;
574} 550}
575 551
576/* receive a packet with the batman ethertype coming on a hard 552/* incoming packets with the batman ethertype received on any active hard
577 * interface */ 553 * interface */
578static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, 554static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
579 struct packet_type *ptype, 555 struct packet_type *ptype,
580 struct net_device *orig_dev) 556 struct net_device *orig_dev)
581{ 557{
582 struct bat_priv *bat_priv; 558 struct bat_priv *bat_priv;
583 struct batman_packet *batman_packet; 559 struct batman_ogm_packet *batman_ogm_packet;
584 struct hard_iface *hard_iface; 560 struct hard_iface *hard_iface;
585 int ret; 561 int ret;
586 562
@@ -612,22 +588,22 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
612 if (hard_iface->if_status != IF_ACTIVE) 588 if (hard_iface->if_status != IF_ACTIVE)
613 goto err_free; 589 goto err_free;
614 590
615 batman_packet = (struct batman_packet *)skb->data; 591 batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
616 592
617 if (batman_packet->version != COMPAT_VERSION) { 593 if (batman_ogm_packet->version != COMPAT_VERSION) {
618 bat_dbg(DBG_BATMAN, bat_priv, 594 bat_dbg(DBG_BATMAN, bat_priv,
619 "Drop packet: incompatible batman version (%i)\n", 595 "Drop packet: incompatible batman version (%i)\n",
620 batman_packet->version); 596 batman_ogm_packet->version);
621 goto err_free; 597 goto err_free;
622 } 598 }
623 599
624 /* all receive handlers return whether they received or reused 600 /* all receive handlers return whether they received or reused
625 * the supplied skb. if not, we have to free the skb. */ 601 * the supplied skb. if not, we have to free the skb. */
626 602
627 switch (batman_packet->packet_type) { 603 switch (batman_ogm_packet->packet_type) {
628 /* batman originator packet */ 604 /* batman originator packet */
629 case BAT_PACKET: 605 case BAT_OGM:
630 ret = recv_bat_packet(skb, hard_iface); 606 ret = recv_bat_ogm_packet(skb, hard_iface);
631 break; 607 break;
632 608
633 /* batman icmp packet */ 609 /* batman icmp packet */
@@ -681,6 +657,36 @@ err_out:
681 return NET_RX_DROP; 657 return NET_RX_DROP;
682} 658}
683 659
660/* This function returns true if the interface represented by ifindex is a
661 * 802.11 wireless device */
662bool is_wifi_iface(int ifindex)
663{
664 struct net_device *net_device = NULL;
665 bool ret = false;
666
667 if (ifindex == NULL_IFINDEX)
668 goto out;
669
670 net_device = dev_get_by_index(&init_net, ifindex);
671 if (!net_device)
672 goto out;
673
674#ifdef CONFIG_WIRELESS_EXT
675 /* pre-cfg80211 drivers have to implement WEXT, so it is possible to
676 * check for wireless_handlers != NULL */
677 if (net_device->wireless_handlers)
678 ret = true;
679 else
680#endif
681 /* cfg80211 drivers have to set ieee80211_ptr */
682 if (net_device->ieee80211_ptr)
683 ret = true;
684out:
685 if (net_device)
686 dev_put(net_device);
687 return ret;
688}
689
684struct notifier_block hard_if_notifier = { 690struct notifier_block hard_if_notifier = {
685 .notifier_call = hard_if_event, 691 .notifier_call = hard_if_event,
686}; 692};
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 442eacbc9e3a..67f78d1a63b4 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -42,6 +42,7 @@ void hardif_remove_interfaces(void);
42int hardif_min_mtu(struct net_device *soft_iface); 42int hardif_min_mtu(struct net_device *soft_iface);
43void update_min_mtu(struct net_device *soft_iface); 43void update_min_mtu(struct net_device *soft_iface);
44void hardif_free_rcu(struct rcu_head *rcu); 44void hardif_free_rcu(struct rcu_head *rcu);
45bool is_wifi_iface(int ifindex);
45 46
46static inline void hardif_free_ref(struct hard_iface *hard_iface) 47static inline void hardif_free_ref(struct hard_iface *hard_iface)
47{ 48{
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index dd5c9fd7a905..d20aa71ba1e8 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -76,19 +76,30 @@ static inline void hash_delete(struct hashtable_t *hash,
76 hash_destroy(hash); 76 hash_destroy(hash);
77} 77}
78 78
79/* adds data to the hashtable. returns 0 on success, -1 on error */ 79/**
80 * hash_add - adds data to the hashtable
81 * @hash: storage hash table
82 * @compare: callback to determine if 2 hash elements are identical
83 * @choose: callback calculating the hash index
84 * @data: data passed to the aforementioned callbacks as argument
85 * @data_node: to be added element
86 *
87 * Returns 0 on success, 1 if the element already is in the hash
88 * and -1 on error.
89 */
90
80static inline int hash_add(struct hashtable_t *hash, 91static inline int hash_add(struct hashtable_t *hash,
81 hashdata_compare_cb compare, 92 hashdata_compare_cb compare,
82 hashdata_choose_cb choose, 93 hashdata_choose_cb choose,
83 const void *data, struct hlist_node *data_node) 94 const void *data, struct hlist_node *data_node)
84{ 95{
85 int index; 96 int index, ret = -1;
86 struct hlist_head *head; 97 struct hlist_head *head;
87 struct hlist_node *node; 98 struct hlist_node *node;
88 spinlock_t *list_lock; /* spinlock to protect write access */ 99 spinlock_t *list_lock; /* spinlock to protect write access */
89 100
90 if (!hash) 101 if (!hash)
91 goto err; 102 goto out;
92 103
93 index = choose(data, hash->size); 104 index = choose(data, hash->size);
94 head = &hash->table[index]; 105 head = &hash->table[index];
@@ -99,6 +110,7 @@ static inline int hash_add(struct hashtable_t *hash,
99 if (!compare(node, data)) 110 if (!compare(node, data))
100 continue; 111 continue;
101 112
113 ret = 1;
102 goto err_unlock; 114 goto err_unlock;
103 } 115 }
104 rcu_read_unlock(); 116 rcu_read_unlock();
@@ -108,12 +120,13 @@ static inline int hash_add(struct hashtable_t *hash,
108 hlist_add_head_rcu(data_node, head); 120 hlist_add_head_rcu(data_node, head);
109 spin_unlock_bh(list_lock); 121 spin_unlock_bh(list_lock);
110 122
111 return 0; 123 ret = 0;
124 goto out;
112 125
113err_unlock: 126err_unlock:
114 rcu_read_unlock(); 127 rcu_read_unlock();
115err: 128out:
116 return -1; 129 return ret;
117} 130}
118 131
119/* removes data from hash, if found. returns pointer do data on success, so you 132/* removes data from hash, if found. returns pointer do data on success, so you
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b0f9068ade57..fb87bdc2ce9b 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -107,7 +107,7 @@ int mesh_init(struct net_device *soft_iface)
107 if (tt_init(bat_priv) < 1) 107 if (tt_init(bat_priv) < 1)
108 goto err; 108 goto err;
109 109
110 tt_local_add(soft_iface, soft_iface->dev_addr); 110 tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
111 111
112 if (vis_init(bat_priv) < 1) 112 if (vis_init(bat_priv) < 1)
113 goto err; 113 goto err;
@@ -117,8 +117,6 @@ int mesh_init(struct net_device *soft_iface)
117 goto end; 117 goto end;
118 118
119err: 119err:
120 pr_err("Unable to allocate memory for mesh information structures: "
121 "out of mem ?\n");
122 mesh_free(soft_iface); 120 mesh_free(soft_iface);
123 return -1; 121 return -1;
124 122
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index a6df61a6933b..964ad4d8ba33 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -28,7 +28,7 @@
28#define DRIVER_DEVICE "batman-adv" 28#define DRIVER_DEVICE "batman-adv"
29 29
30#ifndef SOURCE_VERSION 30#ifndef SOURCE_VERSION
31#define SOURCE_VERSION "2011.3.0" 31#define SOURCE_VERSION "2011.4.0"
32#endif 32#endif
33 33
34/* B.A.T.M.A.N. parameters */ 34/* B.A.T.M.A.N. parameters */
@@ -44,7 +44,7 @@
44#define PURGE_TIMEOUT 200 44#define PURGE_TIMEOUT 200
45#define TT_LOCAL_TIMEOUT 3600 /* in seconds */ 45#define TT_LOCAL_TIMEOUT 3600 /* in seconds */
46#define TT_CLIENT_ROAM_TIMEOUT 600 46#define TT_CLIENT_ROAM_TIMEOUT 600
47/* sliding packet range of received originator messages in squence numbers 47/* sliding packet range of received originator messages in sequence numbers
48 * (should be a multiple of our word size) */ 48 * (should be a multiple of our word size) */
49#define TQ_LOCAL_WINDOW_SIZE 64 49#define TQ_LOCAL_WINDOW_SIZE 64
50#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */ 50#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
@@ -62,6 +62,8 @@
62 62
63#define NO_FLAGS 0 63#define NO_FLAGS 0
64 64
65#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
66
65#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) 67#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
66 68
67#define LOG_BUF_LEN 8192 /* has to be a power of 2 */ 69#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
@@ -133,7 +135,7 @@ enum dbg_level {
133#include <linux/mutex.h> /* mutex */ 135#include <linux/mutex.h> /* mutex */
134#include <linux/module.h> /* needed by all modules */ 136#include <linux/module.h> /* needed by all modules */
135#include <linux/netdevice.h> /* netdevice */ 137#include <linux/netdevice.h> /* netdevice */
136#include <linux/etherdevice.h> /* ethernet address classifaction */ 138#include <linux/etherdevice.h> /* ethernet address classification */
137#include <linux/if_ether.h> /* ethernet header */ 139#include <linux/if_ether.h> /* ethernet header */
138#include <linux/poll.h> /* poll_table */ 140#include <linux/poll.h> /* poll_table */
139#include <linux/kthread.h> /* kernel threads */ 141#include <linux/kthread.h> /* kernel threads */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index f3c3f620d195..0e5b77255d99 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -252,7 +252,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
252 252
253 hash_added = hash_add(bat_priv->orig_hash, compare_orig, 253 hash_added = hash_add(bat_priv->orig_hash, compare_orig,
254 choose_orig, orig_node, &orig_node->hash_entry); 254 choose_orig, orig_node, &orig_node->hash_entry);
255 if (hash_added < 0) 255 if (hash_added != 0)
256 goto free_bcast_own_sum; 256 goto free_bcast_own_sum;
257 257
258 return orig_node; 258 return orig_node;
@@ -336,8 +336,7 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
336 } else { 336 } else {
337 if (purge_orig_neighbors(bat_priv, orig_node, 337 if (purge_orig_neighbors(bat_priv, orig_node,
338 &best_neigh_node)) { 338 &best_neigh_node)) {
339 update_routes(bat_priv, orig_node, 339 update_route(bat_priv, orig_node, best_neigh_node);
340 best_neigh_node);
341 } 340 }
342 } 341 }
343 342
@@ -493,10 +492,8 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
493 492
494 data_ptr = kmalloc(max_if_num * sizeof(unsigned long) * NUM_WORDS, 493 data_ptr = kmalloc(max_if_num * sizeof(unsigned long) * NUM_WORDS,
495 GFP_ATOMIC); 494 GFP_ATOMIC);
496 if (!data_ptr) { 495 if (!data_ptr)
497 pr_err("Can't resize orig: out of memory\n");
498 return -1; 496 return -1;
499 }
500 497
501 memcpy(data_ptr, orig_node->bcast_own, 498 memcpy(data_ptr, orig_node->bcast_own,
502 (max_if_num - 1) * sizeof(unsigned long) * NUM_WORDS); 499 (max_if_num - 1) * sizeof(unsigned long) * NUM_WORDS);
@@ -504,10 +501,8 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
504 orig_node->bcast_own = data_ptr; 501 orig_node->bcast_own = data_ptr;
505 502
506 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); 503 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
507 if (!data_ptr) { 504 if (!data_ptr)
508 pr_err("Can't resize orig: out of memory\n");
509 return -1; 505 return -1;
510 }
511 506
512 memcpy(data_ptr, orig_node->bcast_own_sum, 507 memcpy(data_ptr, orig_node->bcast_own_sum,
513 (max_if_num - 1) * sizeof(uint8_t)); 508 (max_if_num - 1) * sizeof(uint8_t));
@@ -562,10 +557,8 @@ static int orig_node_del_if(struct orig_node *orig_node,
562 557
563 chunk_size = sizeof(unsigned long) * NUM_WORDS; 558 chunk_size = sizeof(unsigned long) * NUM_WORDS;
564 data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC); 559 data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
565 if (!data_ptr) { 560 if (!data_ptr)
566 pr_err("Can't resize orig: out of memory\n");
567 return -1; 561 return -1;
568 }
569 562
570 /* copy first part */ 563 /* copy first part */
571 memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size); 564 memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
@@ -583,10 +576,8 @@ free_bcast_own:
583 goto free_own_sum; 576 goto free_own_sum;
584 577
585 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); 578 data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
586 if (!data_ptr) { 579 if (!data_ptr)
587 pr_err("Can't resize orig: out of memory\n");
588 return -1; 580 return -1;
589 }
590 581
591 memcpy(data_ptr, orig_node->bcast_own_sum, 582 memcpy(data_ptr, orig_node->bcast_own_sum,
592 del_if_num * sizeof(uint8_t)); 583 del_if_num * sizeof(uint8_t));
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index b76b4be10b92..4d9e54c57a36 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -25,14 +25,14 @@
25#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ 25#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
26 26
27enum bat_packettype { 27enum bat_packettype {
28 BAT_PACKET = 0x01, 28 BAT_OGM = 0x01,
29 BAT_ICMP = 0x02, 29 BAT_ICMP = 0x02,
30 BAT_UNICAST = 0x03, 30 BAT_UNICAST = 0x03,
31 BAT_BCAST = 0x04, 31 BAT_BCAST = 0x04,
32 BAT_VIS = 0x05, 32 BAT_VIS = 0x05,
33 BAT_UNICAST_FRAG = 0x06, 33 BAT_UNICAST_FRAG = 0x06,
34 BAT_TT_QUERY = 0x07, 34 BAT_TT_QUERY = 0x07,
35 BAT_ROAM_ADV = 0x08 35 BAT_ROAM_ADV = 0x08
36}; 36};
37 37
38/* this file is included by batctl which needs these defines */ 38/* this file is included by batctl which needs these defines */
@@ -84,12 +84,13 @@ enum tt_query_flags {
84enum tt_client_flags { 84enum tt_client_flags {
85 TT_CLIENT_DEL = 1 << 0, 85 TT_CLIENT_DEL = 1 << 0,
86 TT_CLIENT_ROAM = 1 << 1, 86 TT_CLIENT_ROAM = 1 << 1,
87 TT_CLIENT_WIFI = 1 << 2,
87 TT_CLIENT_NOPURGE = 1 << 8, 88 TT_CLIENT_NOPURGE = 1 << 8,
88 TT_CLIENT_NEW = 1 << 9, 89 TT_CLIENT_NEW = 1 << 9,
89 TT_CLIENT_PENDING = 1 << 10 90 TT_CLIENT_PENDING = 1 << 10
90}; 91};
91 92
92struct batman_packet { 93struct batman_ogm_packet {
93 uint8_t packet_type; 94 uint8_t packet_type;
94 uint8_t version; /* batman version field */ 95 uint8_t version; /* batman version field */
95 uint8_t ttl; 96 uint8_t ttl;
@@ -104,7 +105,7 @@ struct batman_packet {
104 uint16_t tt_crc; 105 uint16_t tt_crc;
105} __packed; 106} __packed;
106 107
107#define BAT_PACKET_LEN sizeof(struct batman_packet) 108#define BATMAN_OGM_LEN sizeof(struct batman_ogm_packet)
108 109
109struct icmp_packet { 110struct icmp_packet {
110 uint8_t packet_type; 111 uint8_t packet_type;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 0f32c818874d..f961cc5eade5 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -22,18 +22,14 @@
22#include "main.h" 22#include "main.h"
23#include "routing.h" 23#include "routing.h"
24#include "send.h" 24#include "send.h"
25#include "hash.h"
26#include "soft-interface.h" 25#include "soft-interface.h"
27#include "hard-interface.h" 26#include "hard-interface.h"
28#include "icmp_socket.h" 27#include "icmp_socket.h"
29#include "translation-table.h" 28#include "translation-table.h"
30#include "originator.h" 29#include "originator.h"
31#include "ring_buffer.h"
32#include "vis.h" 30#include "vis.h"
33#include "aggregation.h"
34#include "gateway_common.h"
35#include "gateway_client.h"
36#include "unicast.h" 31#include "unicast.h"
32#include "bat_ogm.h"
37 33
38void slide_own_bcast_window(struct hard_iface *hard_iface) 34void slide_own_bcast_window(struct hard_iface *hard_iface)
39{ 35{
@@ -64,69 +60,9 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
64 } 60 }
65} 61}
66 62
67static void update_transtable(struct bat_priv *bat_priv, 63static void _update_route(struct bat_priv *bat_priv,
68 struct orig_node *orig_node, 64 struct orig_node *orig_node,
69 const unsigned char *tt_buff, 65 struct neigh_node *neigh_node)
70 uint8_t tt_num_changes, uint8_t ttvn,
71 uint16_t tt_crc)
72{
73 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
74 bool full_table = true;
75
76 /* the ttvn increased by one -> we can apply the attached changes */
77 if (ttvn - orig_ttvn == 1) {
78 /* the OGM could not contain the changes because they were too
79 * many to fit in one frame or because they have already been
80 * sent TT_OGM_APPEND_MAX times. In this case send a tt
81 * request */
82 if (!tt_num_changes) {
83 full_table = false;
84 goto request_table;
85 }
86
87 tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
88 (struct tt_change *)tt_buff);
89
90 /* Even if we received the crc into the OGM, we prefer
91 * to recompute it to spot any possible inconsistency
92 * in the global table */
93 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
94
95 /* The ttvn alone is not enough to guarantee consistency
96 * because a single value could repesent different states
97 * (due to the wrap around). Thus a node has to check whether
98 * the resulting table (after applying the changes) is still
99 * consistent or not. E.g. a node could disconnect while its
100 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
101 * checking the CRC value is mandatory to detect the
102 * inconsistency */
103 if (orig_node->tt_crc != tt_crc)
104 goto request_table;
105
106 /* Roaming phase is over: tables are in sync again. I can
107 * unset the flag */
108 orig_node->tt_poss_change = false;
109 } else {
110 /* if we missed more than one change or our tables are not
111 * in sync anymore -> request fresh tt data */
112 if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
113request_table:
114 bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
115 "Need to retrieve the correct information "
116 "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
117 "%u num_changes: %u)\n", orig_node->orig, ttvn,
118 orig_ttvn, tt_crc, orig_node->tt_crc,
119 tt_num_changes);
120 send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
121 full_table);
122 return;
123 }
124 }
125}
126
127static void update_route(struct bat_priv *bat_priv,
128 struct orig_node *orig_node,
129 struct neigh_node *neigh_node)
130{ 66{
131 struct neigh_node *curr_router; 67 struct neigh_node *curr_router;
132 68
@@ -170,8 +106,8 @@ static void update_route(struct bat_priv *bat_priv,
170 neigh_node_free_ref(curr_router); 106 neigh_node_free_ref(curr_router);
171} 107}
172 108
173void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, 109void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node,
174 struct neigh_node *neigh_node) 110 struct neigh_node *neigh_node)
175{ 111{
176 struct neigh_node *router = NULL; 112 struct neigh_node *router = NULL;
177 113
@@ -181,116 +117,13 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
181 router = orig_node_get_router(orig_node); 117 router = orig_node_get_router(orig_node);
182 118
183 if (router != neigh_node) 119 if (router != neigh_node)
184 update_route(bat_priv, orig_node, neigh_node); 120 _update_route(bat_priv, orig_node, neigh_node);
185 121
186out: 122out:
187 if (router) 123 if (router)
188 neigh_node_free_ref(router); 124 neigh_node_free_ref(router);
189} 125}
190 126
191static int is_bidirectional_neigh(struct orig_node *orig_node,
192 struct orig_node *orig_neigh_node,
193 struct batman_packet *batman_packet,
194 struct hard_iface *if_incoming)
195{
196 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
197 struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
198 struct hlist_node *node;
199 uint8_t total_count;
200 uint8_t orig_eq_count, neigh_rq_count, tq_own;
201 int tq_asym_penalty, ret = 0;
202
203 /* find corresponding one hop neighbor */
204 rcu_read_lock();
205 hlist_for_each_entry_rcu(tmp_neigh_node, node,
206 &orig_neigh_node->neigh_list, list) {
207
208 if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig))
209 continue;
210
211 if (tmp_neigh_node->if_incoming != if_incoming)
212 continue;
213
214 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
215 continue;
216
217 neigh_node = tmp_neigh_node;
218 break;
219 }
220 rcu_read_unlock();
221
222 if (!neigh_node)
223 neigh_node = create_neighbor(orig_neigh_node,
224 orig_neigh_node,
225 orig_neigh_node->orig,
226 if_incoming);
227
228 if (!neigh_node)
229 goto out;
230
231 /* if orig_node is direct neighbour update neigh_node last_valid */
232 if (orig_node == orig_neigh_node)
233 neigh_node->last_valid = jiffies;
234
235 orig_node->last_valid = jiffies;
236
237 /* find packet count of corresponding one hop neighbor */
238 spin_lock_bh(&orig_node->ogm_cnt_lock);
239 orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
240 neigh_rq_count = neigh_node->real_packet_count;
241 spin_unlock_bh(&orig_node->ogm_cnt_lock);
242
243 /* pay attention to not get a value bigger than 100 % */
244 total_count = (orig_eq_count > neigh_rq_count ?
245 neigh_rq_count : orig_eq_count);
246
247 /* if we have too few packets (too less data) we set tq_own to zero */
248 /* if we receive too few packets it is not considered bidirectional */
249 if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
250 (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
251 tq_own = 0;
252 else
253 /* neigh_node->real_packet_count is never zero as we
254 * only purge old information when getting new
255 * information */
256 tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count;
257
258 /*
259 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
260 * affect the nearly-symmetric links only a little, but
261 * punishes asymmetric links more. This will give a value
262 * between 0 and TQ_MAX_VALUE
263 */
264 tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
265 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
266 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
267 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) /
268 (TQ_LOCAL_WINDOW_SIZE *
269 TQ_LOCAL_WINDOW_SIZE *
270 TQ_LOCAL_WINDOW_SIZE);
271
272 batman_packet->tq = ((batman_packet->tq * tq_own * tq_asym_penalty) /
273 (TQ_MAX_VALUE * TQ_MAX_VALUE));
274
275 bat_dbg(DBG_BATMAN, bat_priv,
276 "bidirectional: "
277 "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
278 "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
279 "total tq: %3i\n",
280 orig_node->orig, orig_neigh_node->orig, total_count,
281 neigh_rq_count, tq_own, tq_asym_penalty, batman_packet->tq);
282
283 /* if link has the minimum required transmission quality
284 * consider it bidirectional */
285 if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
286 ret = 1;
287
288out:
289 if (neigh_node)
290 neigh_node_free_ref(neigh_node);
291 return ret;
292}
293
294/* caller must hold the neigh_list_lock */ 127/* caller must hold the neigh_list_lock */
295void bonding_candidate_del(struct orig_node *orig_node, 128void bonding_candidate_del(struct orig_node *orig_node,
296 struct neigh_node *neigh_node) 129 struct neigh_node *neigh_node)
@@ -308,8 +141,8 @@ out:
308 return; 141 return;
309} 142}
310 143
311static void bonding_candidate_add(struct orig_node *orig_node, 144void bonding_candidate_add(struct orig_node *orig_node,
312 struct neigh_node *neigh_node) 145 struct neigh_node *neigh_node)
313{ 146{
314 struct hlist_node *node; 147 struct hlist_node *node;
315 struct neigh_node *tmp_neigh_node, *router = NULL; 148 struct neigh_node *tmp_neigh_node, *router = NULL;
@@ -379,162 +212,23 @@ out:
379} 212}
380 213
381/* copy primary address for bonding */ 214/* copy primary address for bonding */
382static void bonding_save_primary(const struct orig_node *orig_node, 215void bonding_save_primary(const struct orig_node *orig_node,
383 struct orig_node *orig_neigh_node, 216 struct orig_node *orig_neigh_node,
384 const struct batman_packet *batman_packet) 217 const struct batman_ogm_packet *batman_ogm_packet)
385{ 218{
386 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) 219 if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP))
387 return; 220 return;
388 221
389 memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); 222 memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
390} 223}
391 224
392static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
393 const struct ethhdr *ethhdr,
394 const struct batman_packet *batman_packet,
395 struct hard_iface *if_incoming,
396 const unsigned char *tt_buff, int is_duplicate)
397{
398 struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
399 struct neigh_node *router = NULL;
400 struct orig_node *orig_node_tmp;
401 struct hlist_node *node;
402 uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
403
404 bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
405 "Searching and updating originator entry of received packet\n");
406
407 rcu_read_lock();
408 hlist_for_each_entry_rcu(tmp_neigh_node, node,
409 &orig_node->neigh_list, list) {
410 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
411 (tmp_neigh_node->if_incoming == if_incoming) &&
412 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
413 if (neigh_node)
414 neigh_node_free_ref(neigh_node);
415 neigh_node = tmp_neigh_node;
416 continue;
417 }
418
419 if (is_duplicate)
420 continue;
421
422 spin_lock_bh(&tmp_neigh_node->tq_lock);
423 ring_buffer_set(tmp_neigh_node->tq_recv,
424 &tmp_neigh_node->tq_index, 0);
425 tmp_neigh_node->tq_avg =
426 ring_buffer_avg(tmp_neigh_node->tq_recv);
427 spin_unlock_bh(&tmp_neigh_node->tq_lock);
428 }
429
430 if (!neigh_node) {
431 struct orig_node *orig_tmp;
432
433 orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
434 if (!orig_tmp)
435 goto unlock;
436
437 neigh_node = create_neighbor(orig_node, orig_tmp,
438 ethhdr->h_source, if_incoming);
439
440 orig_node_free_ref(orig_tmp);
441 if (!neigh_node)
442 goto unlock;
443 } else
444 bat_dbg(DBG_BATMAN, bat_priv,
445 "Updating existing last-hop neighbor of originator\n");
446
447 rcu_read_unlock();
448
449 orig_node->flags = batman_packet->flags;
450 neigh_node->last_valid = jiffies;
451
452 spin_lock_bh(&neigh_node->tq_lock);
453 ring_buffer_set(neigh_node->tq_recv,
454 &neigh_node->tq_index,
455 batman_packet->tq);
456 neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
457 spin_unlock_bh(&neigh_node->tq_lock);
458
459 if (!is_duplicate) {
460 orig_node->last_ttl = batman_packet->ttl;
461 neigh_node->last_ttl = batman_packet->ttl;
462 }
463
464 bonding_candidate_add(orig_node, neigh_node);
465
466 /* if this neighbor already is our next hop there is nothing
467 * to change */
468 router = orig_node_get_router(orig_node);
469 if (router == neigh_node)
470 goto update_tt;
471
472 /* if this neighbor does not offer a better TQ we won't consider it */
473 if (router && (router->tq_avg > neigh_node->tq_avg))
474 goto update_tt;
475
476 /* if the TQ is the same and the link not more symetric we
477 * won't consider it either */
478 if (router && (neigh_node->tq_avg == router->tq_avg)) {
479 orig_node_tmp = router->orig_node;
480 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
481 bcast_own_sum_orig =
482 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
483 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
484
485 orig_node_tmp = neigh_node->orig_node;
486 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
487 bcast_own_sum_neigh =
488 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
489 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
490
491 if (bcast_own_sum_orig >= bcast_own_sum_neigh)
492 goto update_tt;
493 }
494
495 update_routes(bat_priv, orig_node, neigh_node);
496
497update_tt:
498 /* I have to check for transtable changes only if the OGM has been
499 * sent through a primary interface */
500 if (((batman_packet->orig != ethhdr->h_source) &&
501 (batman_packet->ttl > 2)) ||
502 (batman_packet->flags & PRIMARIES_FIRST_HOP))
503 update_transtable(bat_priv, orig_node, tt_buff,
504 batman_packet->tt_num_changes,
505 batman_packet->ttvn,
506 batman_packet->tt_crc);
507
508 if (orig_node->gw_flags != batman_packet->gw_flags)
509 gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
510
511 orig_node->gw_flags = batman_packet->gw_flags;
512
513 /* restart gateway selection if fast or late switching was enabled */
514 if ((orig_node->gw_flags) &&
515 (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
516 (atomic_read(&bat_priv->gw_sel_class) > 2))
517 gw_check_election(bat_priv, orig_node);
518
519 goto out;
520
521unlock:
522 rcu_read_unlock();
523out:
524 if (neigh_node)
525 neigh_node_free_ref(neigh_node);
526 if (router)
527 neigh_node_free_ref(router);
528}
529
530/* checks whether the host restarted and is in the protection time. 225/* checks whether the host restarted and is in the protection time.
531 * returns: 226 * returns:
532 * 0 if the packet is to be accepted 227 * 0 if the packet is to be accepted
533 * 1 if the packet is to be ignored. 228 * 1 if the packet is to be ignored.
534 */ 229 */
535static int window_protected(struct bat_priv *bat_priv, 230int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff,
536 int32_t seq_num_diff, 231 unsigned long *last_reset)
537 unsigned long *last_reset)
538{ 232{
539 if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) 233 if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
540 || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { 234 || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
@@ -552,330 +246,12 @@ static int window_protected(struct bat_priv *bat_priv,
552 return 0; 246 return 0;
553} 247}
554 248
555/* processes a batman packet for all interfaces, adjusts the sequence number and 249int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
556 * finds out whether it is a duplicate.
557 * returns:
558 * 1 the packet is a duplicate
559 * 0 the packet has not yet been received
560 * -1 the packet is old and has been received while the seqno window
561 * was protected. Caller should drop it.
562 */
563static int count_real_packets(const struct ethhdr *ethhdr,
564 const struct batman_packet *batman_packet,
565 const struct hard_iface *if_incoming)
566{
567 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
568 struct orig_node *orig_node;
569 struct neigh_node *tmp_neigh_node;
570 struct hlist_node *node;
571 int is_duplicate = 0;
572 int32_t seq_diff;
573 int need_update = 0;
574 int set_mark, ret = -1;
575
576 orig_node = get_orig_node(bat_priv, batman_packet->orig);
577 if (!orig_node)
578 return 0;
579
580 spin_lock_bh(&orig_node->ogm_cnt_lock);
581 seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
582
583 /* signalize caller that the packet is to be dropped. */
584 if (window_protected(bat_priv, seq_diff,
585 &orig_node->batman_seqno_reset))
586 goto out;
587
588 rcu_read_lock();
589 hlist_for_each_entry_rcu(tmp_neigh_node, node,
590 &orig_node->neigh_list, list) {
591
592 is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
593 orig_node->last_real_seqno,
594 batman_packet->seqno);
595
596 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
597 (tmp_neigh_node->if_incoming == if_incoming))
598 set_mark = 1;
599 else
600 set_mark = 0;
601
602 /* if the window moved, set the update flag. */
603 need_update |= bit_get_packet(bat_priv,
604 tmp_neigh_node->real_bits,
605 seq_diff, set_mark);
606
607 tmp_neigh_node->real_packet_count =
608 bit_packet_count(tmp_neigh_node->real_bits);
609 }
610 rcu_read_unlock();
611
612 if (need_update) {
613 bat_dbg(DBG_BATMAN, bat_priv,
614 "updating last_seqno: old %d, new %d\n",
615 orig_node->last_real_seqno, batman_packet->seqno);
616 orig_node->last_real_seqno = batman_packet->seqno;
617 }
618
619 ret = is_duplicate;
620
621out:
622 spin_unlock_bh(&orig_node->ogm_cnt_lock);
623 orig_node_free_ref(orig_node);
624 return ret;
625}
626
627void receive_bat_packet(const struct ethhdr *ethhdr,
628 struct batman_packet *batman_packet,
629 const unsigned char *tt_buff,
630 struct hard_iface *if_incoming)
631{
632 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
633 struct hard_iface *hard_iface;
634 struct orig_node *orig_neigh_node, *orig_node;
635 struct neigh_node *router = NULL, *router_router = NULL;
636 struct neigh_node *orig_neigh_router = NULL;
637 int has_directlink_flag;
638 int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
639 int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
640 int is_duplicate;
641 uint32_t if_incoming_seqno;
642
643 /* Silently drop when the batman packet is actually not a
644 * correct packet.
645 *
646 * This might happen if a packet is padded (e.g. Ethernet has a
647 * minimum frame length of 64 byte) and the aggregation interprets
648 * it as an additional length.
649 *
650 * TODO: A more sane solution would be to have a bit in the
651 * batman_packet to detect whether the packet is the last
652 * packet in an aggregation. Here we expect that the padding
653 * is always zero (or not 0x01)
654 */
655 if (batman_packet->packet_type != BAT_PACKET)
656 return;
657
658 /* could be changed by schedule_own_packet() */
659 if_incoming_seqno = atomic_read(&if_incoming->seqno);
660
661 has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
662
663 is_single_hop_neigh = (compare_eth(ethhdr->h_source,
664 batman_packet->orig) ? 1 : 0);
665
666 bat_dbg(DBG_BATMAN, bat_priv,
667 "Received BATMAN packet via NB: %pM, IF: %s [%pM] "
668 "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, "
669 "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
670 ethhdr->h_source, if_incoming->net_dev->name,
671 if_incoming->net_dev->dev_addr, batman_packet->orig,
672 batman_packet->prev_sender, batman_packet->seqno,
673 batman_packet->ttvn, batman_packet->tt_crc,
674 batman_packet->tt_num_changes, batman_packet->tq,
675 batman_packet->ttl, batman_packet->version,
676 has_directlink_flag);
677
678 rcu_read_lock();
679 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
680 if (hard_iface->if_status != IF_ACTIVE)
681 continue;
682
683 if (hard_iface->soft_iface != if_incoming->soft_iface)
684 continue;
685
686 if (compare_eth(ethhdr->h_source,
687 hard_iface->net_dev->dev_addr))
688 is_my_addr = 1;
689
690 if (compare_eth(batman_packet->orig,
691 hard_iface->net_dev->dev_addr))
692 is_my_orig = 1;
693
694 if (compare_eth(batman_packet->prev_sender,
695 hard_iface->net_dev->dev_addr))
696 is_my_oldorig = 1;
697
698 if (is_broadcast_ether_addr(ethhdr->h_source))
699 is_broadcast = 1;
700 }
701 rcu_read_unlock();
702
703 if (batman_packet->version != COMPAT_VERSION) {
704 bat_dbg(DBG_BATMAN, bat_priv,
705 "Drop packet: incompatible batman version (%i)\n",
706 batman_packet->version);
707 return;
708 }
709
710 if (is_my_addr) {
711 bat_dbg(DBG_BATMAN, bat_priv,
712 "Drop packet: received my own broadcast (sender: %pM"
713 ")\n",
714 ethhdr->h_source);
715 return;
716 }
717
718 if (is_broadcast) {
719 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
720 "ignoring all packets with broadcast source addr (sender: %pM"
721 ")\n", ethhdr->h_source);
722 return;
723 }
724
725 if (is_my_orig) {
726 unsigned long *word;
727 int offset;
728
729 orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
730 if (!orig_neigh_node)
731 return;
732
733 /* neighbor has to indicate direct link and it has to
734 * come via the corresponding interface */
735 /* save packet seqno for bidirectional check */
736 if (has_directlink_flag &&
737 compare_eth(if_incoming->net_dev->dev_addr,
738 batman_packet->orig)) {
739 offset = if_incoming->if_num * NUM_WORDS;
740
741 spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
742 word = &(orig_neigh_node->bcast_own[offset]);
743 bit_mark(word,
744 if_incoming_seqno - batman_packet->seqno - 2);
745 orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
746 bit_packet_count(word);
747 spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
748 }
749
750 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
751 "originator packet from myself (via neighbor)\n");
752 orig_node_free_ref(orig_neigh_node);
753 return;
754 }
755
756 if (is_my_oldorig) {
757 bat_dbg(DBG_BATMAN, bat_priv,
758 "Drop packet: ignoring all rebroadcast echos (sender: "
759 "%pM)\n", ethhdr->h_source);
760 return;
761 }
762
763 orig_node = get_orig_node(bat_priv, batman_packet->orig);
764 if (!orig_node)
765 return;
766
767 is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
768
769 if (is_duplicate == -1) {
770 bat_dbg(DBG_BATMAN, bat_priv,
771 "Drop packet: packet within seqno protection time "
772 "(sender: %pM)\n", ethhdr->h_source);
773 goto out;
774 }
775
776 if (batman_packet->tq == 0) {
777 bat_dbg(DBG_BATMAN, bat_priv,
778 "Drop packet: originator packet with tq equal 0\n");
779 goto out;
780 }
781
782 router = orig_node_get_router(orig_node);
783 if (router)
784 router_router = orig_node_get_router(router->orig_node);
785
786 /* avoid temporary routing loops */
787 if (router && router_router &&
788 (compare_eth(router->addr, batman_packet->prev_sender)) &&
789 !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) &&
790 (compare_eth(router->addr, router_router->addr))) {
791 bat_dbg(DBG_BATMAN, bat_priv,
792 "Drop packet: ignoring all rebroadcast packets that "
793 "may make me loop (sender: %pM)\n", ethhdr->h_source);
794 goto out;
795 }
796
797 /* if sender is a direct neighbor the sender mac equals
798 * originator mac */
799 orig_neigh_node = (is_single_hop_neigh ?
800 orig_node :
801 get_orig_node(bat_priv, ethhdr->h_source));
802 if (!orig_neigh_node)
803 goto out;
804
805 orig_neigh_router = orig_node_get_router(orig_neigh_node);
806
807 /* drop packet if sender is not a direct neighbor and if we
808 * don't route towards it */
809 if (!is_single_hop_neigh && (!orig_neigh_router)) {
810 bat_dbg(DBG_BATMAN, bat_priv,
811 "Drop packet: OGM via unknown neighbor!\n");
812 goto out_neigh;
813 }
814
815 is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
816 batman_packet, if_incoming);
817
818 bonding_save_primary(orig_node, orig_neigh_node, batman_packet);
819
820 /* update ranking if it is not a duplicate or has the same
821 * seqno and similar ttl as the non-duplicate */
822 if (is_bidirectional &&
823 (!is_duplicate ||
824 ((orig_node->last_real_seqno == batman_packet->seqno) &&
825 (orig_node->last_ttl - 3 <= batman_packet->ttl))))
826 update_orig(bat_priv, orig_node, ethhdr, batman_packet,
827 if_incoming, tt_buff, is_duplicate);
828
829 /* is single hop (direct) neighbor */
830 if (is_single_hop_neigh) {
831
832 /* mark direct link on incoming interface */
833 schedule_forward_packet(orig_node, ethhdr, batman_packet,
834 1, if_incoming);
835
836 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
837 "rebroadcast neighbor packet with direct link flag\n");
838 goto out_neigh;
839 }
840
841 /* multihop originator */
842 if (!is_bidirectional) {
843 bat_dbg(DBG_BATMAN, bat_priv,
844 "Drop packet: not received via bidirectional link\n");
845 goto out_neigh;
846 }
847
848 if (is_duplicate) {
849 bat_dbg(DBG_BATMAN, bat_priv,
850 "Drop packet: duplicate packet received\n");
851 goto out_neigh;
852 }
853
854 bat_dbg(DBG_BATMAN, bat_priv,
855 "Forwarding packet: rebroadcast originator packet\n");
856 schedule_forward_packet(orig_node, ethhdr, batman_packet,
857 0, if_incoming);
858
859out_neigh:
860 if ((orig_neigh_node) && (!is_single_hop_neigh))
861 orig_node_free_ref(orig_neigh_node);
862out:
863 if (router)
864 neigh_node_free_ref(router);
865 if (router_router)
866 neigh_node_free_ref(router_router);
867 if (orig_neigh_router)
868 neigh_node_free_ref(orig_neigh_router);
869
870 orig_node_free_ref(orig_node);
871}
872
873int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
874{ 250{
875 struct ethhdr *ethhdr; 251 struct ethhdr *ethhdr;
876 252
877 /* drop packet if it has not necessary minimum size */ 253 /* drop packet if it has not necessary minimum size */
878 if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet)))) 254 if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_LEN)))
879 return NET_RX_DROP; 255 return NET_RX_DROP;
880 256
881 ethhdr = (struct ethhdr *)skb_mac_header(skb); 257 ethhdr = (struct ethhdr *)skb_mac_header(skb);
@@ -898,10 +274,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
898 274
899 ethhdr = (struct ethhdr *)skb_mac_header(skb); 275 ethhdr = (struct ethhdr *)skb_mac_header(skb);
900 276
901 receive_aggr_bat_packet(ethhdr, 277 bat_ogm_receive(ethhdr, skb->data, skb_headlen(skb), hard_iface);
902 skb->data,
903 skb_headlen(skb),
904 hard_iface);
905 278
906 kfree_skb(skb); 279 kfree_skb(skb);
907 return NET_RX_SUCCESS; 280 return NET_RX_SUCCESS;
@@ -1243,7 +616,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
1243 } 616 }
1244 break; 617 break;
1245 case TT_RESPONSE: 618 case TT_RESPONSE:
1246 /* packet needs to be linearised to access the TT changes */ 619 /* packet needs to be linearized to access the TT changes */
1247 if (skb_linearize(skb) < 0) 620 if (skb_linearize(skb) < 0)
1248 goto out; 621 goto out;
1249 622
@@ -1300,7 +673,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
1300 roam_adv_packet->client); 673 roam_adv_packet->client);
1301 674
1302 tt_global_add(bat_priv, orig_node, roam_adv_packet->client, 675 tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
1303 atomic_read(&orig_node->last_ttvn) + 1, true); 676 atomic_read(&orig_node->last_ttvn) + 1, true, false);
1304 677
1305 /* Roaming phase starts: I have new information but the ttvn has not 678 /* Roaming phase starts: I have new information but the ttvn has not
1306 * been incremented yet. This flag will make me check all the incoming 679 * been incremented yet. This flag will make me check all the incoming
@@ -1536,7 +909,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
1536 909
1537 ethhdr = (struct ethhdr *)(skb->data + 910 ethhdr = (struct ethhdr *)(skb->data +
1538 sizeof(struct unicast_packet)); 911 sizeof(struct unicast_packet));
1539 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 912 orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest);
1540 913
1541 if (!orig_node) { 914 if (!orig_node) {
1542 if (!is_my_client(bat_priv, ethhdr->h_dest)) 915 if (!is_my_client(bat_priv, ethhdr->h_dest))
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index fb14e9579b19..7aaee0fb0fdc 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -23,19 +23,15 @@
23#define _NET_BATMAN_ADV_ROUTING_H_ 23#define _NET_BATMAN_ADV_ROUTING_H_
24 24
25void slide_own_bcast_window(struct hard_iface *hard_iface); 25void slide_own_bcast_window(struct hard_iface *hard_iface);
26void receive_bat_packet(const struct ethhdr *ethhdr, 26void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node,
27 struct batman_packet *batman_packet, 27 struct neigh_node *neigh_node);
28 const unsigned char *tt_buff,
29 struct hard_iface *if_incoming);
30void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
31 struct neigh_node *neigh_node);
32int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); 28int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
33int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); 29int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
34int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); 30int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
35int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if); 31int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if);
36int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if); 32int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
37int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if); 33int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
38int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if); 34int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *recv_if);
39int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if); 35int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if);
40int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if); 36int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if);
41struct neigh_node *find_router(struct bat_priv *bat_priv, 37struct neigh_node *find_router(struct bat_priv *bat_priv,
@@ -43,5 +39,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
43 const struct hard_iface *recv_if); 39 const struct hard_iface *recv_if);
44void bonding_candidate_del(struct orig_node *orig_node, 40void bonding_candidate_del(struct orig_node *orig_node,
45 struct neigh_node *neigh_node); 41 struct neigh_node *neigh_node);
42void bonding_candidate_add(struct orig_node *orig_node,
43 struct neigh_node *neigh_node);
44void bonding_save_primary(const struct orig_node *orig_node,
45 struct orig_node *orig_neigh_node,
46 const struct batman_ogm_packet *batman_ogm_packet);
47int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff,
48 unsigned long *last_reset);
46 49
47#endif /* _NET_BATMAN_ADV_ROUTING_H_ */ 50#endif /* _NET_BATMAN_ADV_ROUTING_H_ */
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 58d14472068c..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,141 +78,17 @@ 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_packet *batman_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_packet = (struct batman_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_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_packet->flags |= DIRECTLINK;
130 else
131 batman_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, hvn %d) on interface %s [%pM]\n",
139 fwd_str, (packet_num > 0 ? "aggregated " : ""),
140 batman_packet->orig, ntohl(batman_packet->seqno),
141 batman_packet->tq, batman_packet->ttl,
142 (batman_packet->flags & DIRECTLINK ?
143 "on" : "off"),
144 batman_packet->ttvn, hard_iface->net_dev->name,
145 hard_iface->net_dev->dev_addr);
146
147 buff_pos += sizeof(*batman_packet) +
148 tt_len(batman_packet->tt_num_changes);
149 packet_num++;
150 batman_packet = (struct batman_packet *)
151 (forw_packet->skb->data + buff_pos);
152 }
153
154 /* create clone because function is called more than once */
155 skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
156 if (skb)
157 send_skb_packet(skb, hard_iface, broadcast_addr);
158}
159
160/* send a batman packet */
161static void send_packet(struct forw_packet *forw_packet)
162{
163 struct hard_iface *hard_iface;
164 struct net_device *soft_iface;
165 struct bat_priv *bat_priv;
166 struct hard_iface *primary_if = NULL;
167 struct batman_packet *batman_packet =
168 (struct batman_packet *)(forw_packet->skb->data);
169 int directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
170
171 if (!forw_packet->if_incoming) {
172 pr_err("Error - can't forward packet: incoming iface not "
173 "specified\n");
174 goto out;
175 }
176
177 soft_iface = forw_packet->if_incoming->soft_iface;
178 bat_priv = netdev_priv(soft_iface);
179
180 if (forw_packet->if_incoming->if_status != IF_ACTIVE)
181 goto out;
182
183 primary_if = primary_if_get_selected(bat_priv);
184 if (!primary_if)
185 goto out;
186
187 /* multihomed peer assumed */
188 /* non-primary OGMs are only broadcasted on their interface */
189 if ((directlink && (batman_packet->ttl == 1)) ||
190 (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
191
192 /* FIXME: what about aggregated packets ? */
193 bat_dbg(DBG_BATMAN, bat_priv,
194 "%s packet (originator %pM, seqno %d, TTL %d) "
195 "on interface %s [%pM]\n",
196 (forw_packet->own ? "Sending own" : "Forwarding"),
197 batman_packet->orig, ntohl(batman_packet->seqno),
198 batman_packet->ttl,
199 forw_packet->if_incoming->net_dev->name,
200 forw_packet->if_incoming->net_dev->dev_addr);
201
202 /* skb is only used once and than forw_packet is free'd */
203 send_skb_packet(forw_packet->skb, forw_packet->if_incoming,
204 broadcast_addr);
205 forw_packet->skb = NULL;
206
207 goto out;
208 }
209
210 /* broadcast on every interface */
211 rcu_read_lock();
212 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
213 if (hard_iface->soft_iface != soft_iface)
214 continue;
215
216 send_packet_to_if(forw_packet, hard_iface);
217 }
218 rcu_read_unlock();
219
220out:
221 if (primary_if)
222 hardif_free_ref(primary_if);
223}
224
225static void realloc_packet_buffer(struct hard_iface *hard_iface, 81static void realloc_packet_buffer(struct hard_iface *hard_iface,
226 int new_len) 82 int new_len)
227{ 83{
228 unsigned char *new_buff; 84 unsigned char *new_buff;
229 struct batman_packet *batman_packet;
230 85
231 new_buff = kmalloc(new_len, GFP_ATOMIC); 86 new_buff = kmalloc(new_len, GFP_ATOMIC);
232 87
233 /* keep old buffer if kmalloc should fail */ 88 /* keep old buffer if kmalloc should fail */
234 if (new_buff) { 89 if (new_buff) {
235 memcpy(new_buff, hard_iface->packet_buff, 90 memcpy(new_buff, hard_iface->packet_buff,
236 sizeof(*batman_packet)); 91 BATMAN_OGM_LEN);
237 92
238 kfree(hard_iface->packet_buff); 93 kfree(hard_iface->packet_buff);
239 hard_iface->packet_buff = new_buff; 94 hard_iface->packet_buff = new_buff;
@@ -242,60 +97,48 @@ static void realloc_packet_buffer(struct hard_iface *hard_iface,
242} 97}
243 98
244/* 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 */
245static void prepare_packet_buffer(struct bat_priv *bat_priv, 100static int prepare_packet_buffer(struct bat_priv *bat_priv,
246 struct hard_iface *hard_iface) 101 struct hard_iface *hard_iface)
247{ 102{
248 int new_len; 103 int new_len;
249 struct batman_packet *batman_packet;
250 104
251 new_len = BAT_PACKET_LEN + 105 new_len = BATMAN_OGM_LEN +
252 tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes)); 106 tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
253 107
254 /* if we have too many changes for one packet don't send any 108 /* if we have too many changes for one packet don't send any
255 * and wait for the tt table request which will be fragmented */ 109 * and wait for the tt table request which will be fragmented */
256 if (new_len > hard_iface->soft_iface->mtu) 110 if (new_len > hard_iface->soft_iface->mtu)
257 new_len = BAT_PACKET_LEN; 111 new_len = BATMAN_OGM_LEN;
258 112
259 realloc_packet_buffer(hard_iface, new_len); 113 realloc_packet_buffer(hard_iface, new_len);
260 batman_packet = (struct batman_packet *)hard_iface->packet_buff;
261 114
262 atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv)); 115 atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
263 116
264 /* reset the sending counter */ 117 /* reset the sending counter */
265 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);
266 119
267 batman_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv, 120 return tt_changes_fill_buffer(bat_priv,
268 hard_iface->packet_buff + BAT_PACKET_LEN, 121 hard_iface->packet_buff + BATMAN_OGM_LEN,
269 hard_iface->packet_len - BAT_PACKET_LEN); 122 hard_iface->packet_len - BATMAN_OGM_LEN);
270
271} 123}
272 124
273static void reset_packet_buffer(struct bat_priv *bat_priv, 125static int reset_packet_buffer(struct bat_priv *bat_priv,
274 struct hard_iface *hard_iface) 126 struct hard_iface *hard_iface)
275{ 127{
276 struct batman_packet *batman_packet; 128 realloc_packet_buffer(hard_iface, BATMAN_OGM_LEN);
277 129 return 0;
278 realloc_packet_buffer(hard_iface, BAT_PACKET_LEN);
279
280 batman_packet = (struct batman_packet *)hard_iface->packet_buff;
281 batman_packet->tt_num_changes = 0;
282} 130}
283 131
284void schedule_own_packet(struct hard_iface *hard_iface) 132void schedule_bat_ogm(struct hard_iface *hard_iface)
285{ 133{
286 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 134 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
287 struct hard_iface *primary_if; 135 struct hard_iface *primary_if;
288 unsigned long send_time; 136 int tt_num_changes = -1;
289 struct batman_packet *batman_packet;
290 int vis_server;
291 137
292 if ((hard_iface->if_status == IF_NOT_IN_USE) || 138 if ((hard_iface->if_status == IF_NOT_IN_USE) ||
293 (hard_iface->if_status == IF_TO_BE_REMOVED)) 139 (hard_iface->if_status == IF_TO_BE_REMOVED))
294 return; 140 return;
295 141
296 vis_server = atomic_read(&bat_priv->vis_mode);
297 primary_if = primary_if_get_selected(bat_priv);
298
299 /** 142 /**
300 * the interface gets activated here to avoid race conditions between 143 * the interface gets activated here to avoid race conditions between
301 * the moment of activating the interface in 144 * the moment of activating the interface in
@@ -306,124 +149,26 @@ void schedule_own_packet(struct hard_iface *hard_iface)
306 if (hard_iface->if_status == IF_TO_BE_ACTIVATED) 149 if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
307 hard_iface->if_status = IF_ACTIVE; 150 hard_iface->if_status = IF_ACTIVE;
308 151
152 primary_if = primary_if_get_selected(bat_priv);
153
309 if (hard_iface == primary_if) { 154 if (hard_iface == primary_if) {
310 /* if at least one change happened */ 155 /* if at least one change happened */
311 if (atomic_read(&bat_priv->tt_local_changes) > 0) { 156 if (atomic_read(&bat_priv->tt_local_changes) > 0) {
312 tt_commit_changes(bat_priv); 157 tt_commit_changes(bat_priv);
313 prepare_packet_buffer(bat_priv, hard_iface); 158 tt_num_changes = prepare_packet_buffer(bat_priv,
159 hard_iface);
314 } 160 }
315 161
316 /* if the changes have been sent enough times */ 162 /* if the changes have been sent often enough */
317 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt)) 163 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
318 reset_packet_buffer(bat_priv, hard_iface); 164 tt_num_changes = reset_packet_buffer(bat_priv,
165 hard_iface);
319 } 166 }
320 167
321 /**
322 * NOTE: packet_buff might just have been re-allocated in
323 * prepare_packet_buffer() or in reset_packet_buffer()
324 */
325 batman_packet = (struct batman_packet *)hard_iface->packet_buff;
326
327 /* change sequence number to network order */
328 batman_packet->seqno =
329 htonl((uint32_t)atomic_read(&hard_iface->seqno));
330
331 batman_packet->ttvn = atomic_read(&bat_priv->ttvn);
332 batman_packet->tt_crc = htons((uint16_t)atomic_read(&bat_priv->tt_crc));
333
334 if (vis_server == VIS_TYPE_SERVER_SYNC)
335 batman_packet->flags |= VIS_SERVER;
336 else
337 batman_packet->flags &= ~VIS_SERVER;
338
339 if ((hard_iface == primary_if) &&
340 (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
341 batman_packet->gw_flags =
342 (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
343 else
344 batman_packet->gw_flags = NO_FLAGS;
345
346 atomic_inc(&hard_iface->seqno);
347
348 slide_own_bcast_window(hard_iface);
349 send_time = own_send_time(bat_priv);
350 add_bat_packet_to_list(bat_priv,
351 hard_iface->packet_buff,
352 hard_iface->packet_len,
353 hard_iface, 1, send_time);
354
355 if (primary_if) 168 if (primary_if)
356 hardif_free_ref(primary_if); 169 hardif_free_ref(primary_if);
357}
358
359void schedule_forward_packet(struct orig_node *orig_node,
360 const struct ethhdr *ethhdr,
361 struct batman_packet *batman_packet,
362 int directlink,
363 struct hard_iface *if_incoming)
364{
365 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
366 struct neigh_node *router;
367 uint8_t in_tq, in_ttl, tq_avg = 0;
368 unsigned long send_time;
369 uint8_t tt_num_changes;
370
371 if (batman_packet->ttl <= 1) {
372 bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
373 return;
374 }
375
376 router = orig_node_get_router(orig_node);
377
378 in_tq = batman_packet->tq;
379 in_ttl = batman_packet->ttl;
380 tt_num_changes = batman_packet->tt_num_changes;
381
382 batman_packet->ttl--;
383 memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
384
385 /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
386 * of our best tq value */
387 if (router && router->tq_avg != 0) {
388
389 /* rebroadcast ogm of best ranking neighbor as is */
390 if (!compare_eth(router->addr, ethhdr->h_source)) {
391 batman_packet->tq = router->tq_avg;
392
393 if (router->last_ttl)
394 batman_packet->ttl = router->last_ttl - 1;
395 }
396
397 tq_avg = router->tq_avg;
398 }
399
400 if (router)
401 neigh_node_free_ref(router);
402
403 /* apply hop penalty */
404 batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv);
405
406 bat_dbg(DBG_BATMAN, bat_priv,
407 "Forwarding packet: tq_orig: %i, tq_avg: %i, "
408 "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
409 in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
410 batman_packet->ttl);
411
412 batman_packet->seqno = htonl(batman_packet->seqno);
413 batman_packet->tt_crc = htons(batman_packet->tt_crc);
414
415 /* switch of primaries first hop flag when forwarding */
416 batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
417 if (directlink)
418 batman_packet->flags |= DIRECTLINK;
419 else
420 batman_packet->flags &= ~DIRECTLINK;
421 170
422 send_time = forward_send_time(); 171 bat_ogm_schedule(hard_iface, tt_num_changes);
423 add_bat_packet_to_list(bat_priv,
424 (unsigned char *)batman_packet,
425 sizeof(*batman_packet) + tt_len(tt_num_changes),
426 if_incoming, 0, send_time);
427} 172}
428 173
429static void forw_packet_free(struct forw_packet *forw_packet) 174static void forw_packet_free(struct forw_packet *forw_packet)
@@ -454,7 +199,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
454} 199}
455 200
456/* add a broadcast packet to the queue and setup timers. broadcast packets 201/* add a broadcast packet to the queue and setup timers. broadcast packets
457 * are sent multiple times to increase probability for beeing received. 202 * are sent multiple times to increase probability for being received.
458 * 203 *
459 * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on 204 * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
460 * errors. 205 * errors.
@@ -557,7 +302,7 @@ out:
557 atomic_inc(&bat_priv->bcast_queue_left); 302 atomic_inc(&bat_priv->bcast_queue_left);
558} 303}
559 304
560void send_outstanding_bat_packet(struct work_struct *work) 305void send_outstanding_bat_ogm_packet(struct work_struct *work)
561{ 306{
562 struct delayed_work *delayed_work = 307 struct delayed_work *delayed_work =
563 container_of(work, struct delayed_work, work); 308 container_of(work, struct delayed_work, work);
@@ -573,7 +318,7 @@ void send_outstanding_bat_packet(struct work_struct *work)
573 if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING) 318 if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING)
574 goto out; 319 goto out;
575 320
576 send_packet(forw_packet); 321 bat_ogm_emit(forw_packet);
577 322
578 /** 323 /**
579 * we have to have at least one packet in the queue 324 * we have to have at least one packet in the queue
@@ -581,7 +326,7 @@ void send_outstanding_bat_packet(struct work_struct *work)
581 * shutting down 326 * shutting down
582 */ 327 */
583 if (forw_packet->own) 328 if (forw_packet->own)
584 schedule_own_packet(forw_packet->if_incoming); 329 schedule_bat_ogm(forw_packet->if_incoming);
585 330
586out: 331out:
587 /* don't count own packet */ 332 /* don't count own packet */
@@ -612,7 +357,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
612 &bat_priv->forw_bcast_list, list) { 357 &bat_priv->forw_bcast_list, list) {
613 358
614 /** 359 /**
615 * if purge_outstanding_packets() was called with an argmument 360 * if purge_outstanding_packets() was called with an argument
616 * we delete only packets belonging to the given interface 361 * we delete only packets belonging to the given interface
617 */ 362 */
618 if ((hard_iface) && 363 if ((hard_iface) &&
@@ -641,7 +386,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
641 &bat_priv->forw_bat_list, list) { 386 &bat_priv->forw_bat_list, list) {
642 387
643 /** 388 /**
644 * if purge_outstanding_packets() was called with an argmument 389 * if purge_outstanding_packets() was called with an argument
645 * we delete only packets belonging to the given interface 390 * we delete only packets belonging to the given interface
646 */ 391 */
647 if ((hard_iface) && 392 if ((hard_iface) &&
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 1f2d1e877663..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_packet *batman_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
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 05dd35114a27..f9cc95728989 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -445,30 +445,31 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
445{ 445{
446 struct bat_priv *bat_priv = netdev_priv(dev); 446 struct bat_priv *bat_priv = netdev_priv(dev);
447 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 447 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
448 struct batman_packet *batman_packet; 448 struct batman_ogm_packet *batman_ogm_packet;
449 struct softif_neigh *softif_neigh = NULL; 449 struct softif_neigh *softif_neigh = NULL;
450 struct hard_iface *primary_if = NULL; 450 struct hard_iface *primary_if = NULL;
451 struct softif_neigh *curr_softif_neigh = NULL; 451 struct softif_neigh *curr_softif_neigh = NULL;
452 452
453 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) 453 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
454 batman_packet = (struct batman_packet *) 454 batman_ogm_packet = (struct batman_ogm_packet *)
455 (skb->data + ETH_HLEN + VLAN_HLEN); 455 (skb->data + ETH_HLEN + VLAN_HLEN);
456 else 456 else
457 batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); 457 batman_ogm_packet = (struct batman_ogm_packet *)
458 (skb->data + ETH_HLEN);
458 459
459 if (batman_packet->version != COMPAT_VERSION) 460 if (batman_ogm_packet->version != COMPAT_VERSION)
460 goto out; 461 goto out;
461 462
462 if (batman_packet->packet_type != BAT_PACKET) 463 if (batman_ogm_packet->packet_type != BAT_OGM)
463 goto out; 464 goto out;
464 465
465 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) 466 if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP))
466 goto out; 467 goto out;
467 468
468 if (is_my_mac(batman_packet->orig)) 469 if (is_my_mac(batman_ogm_packet->orig))
469 goto out; 470 goto out;
470 471
471 softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); 472 softif_neigh = softif_neigh_get(bat_priv, batman_ogm_packet->orig, vid);
472 if (!softif_neigh) 473 if (!softif_neigh)
473 goto out; 474 goto out;
474 475
@@ -532,11 +533,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
532 if (!is_valid_ether_addr(addr->sa_data)) 533 if (!is_valid_ether_addr(addr->sa_data))
533 return -EADDRNOTAVAIL; 534 return -EADDRNOTAVAIL;
534 535
535 /* only modify transtable if it has been initialised before */ 536 /* only modify transtable if it has been initialized before */
536 if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { 537 if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
537 tt_local_remove(bat_priv, dev->dev_addr, 538 tt_local_remove(bat_priv, dev->dev_addr,
538 "mac address changed", false); 539 "mac address changed", false);
539 tt_local_add(dev, addr->sa_data); 540 tt_local_add(dev, addr->sa_data, NULL_IFINDEX);
540 } 541 }
541 542
542 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); 543 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -595,11 +596,12 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
595 goto dropped; 596 goto dropped;
596 597
597 /* Register the client MAC in the transtable */ 598 /* Register the client MAC in the transtable */
598 tt_local_add(soft_iface, ethhdr->h_source); 599 tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
599 600
600 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 601 orig_node = transtable_search(bat_priv, ethhdr->h_source,
602 ethhdr->h_dest);
601 do_bcast = is_multicast_ether_addr(ethhdr->h_dest); 603 do_bcast = is_multicast_ether_addr(ethhdr->h_dest);
602 if (do_bcast || (orig_node && orig_node->gw_flags)) { 604 if (do_bcast || (orig_node && orig_node->gw_flags)) {
603 ret = gw_is_target(bat_priv, skb, orig_node); 605 ret = gw_is_target(bat_priv, skb, orig_node);
604 606
605 if (ret < 0) 607 if (ret < 0)
@@ -739,6 +741,9 @@ void interface_rx(struct net_device *soft_iface,
739 741
740 soft_iface->last_rx = jiffies; 742 soft_iface->last_rx = jiffies;
741 743
744 if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
745 goto dropped;
746
742 netif_rx(skb); 747 netif_rx(skb);
743 goto out; 748 goto out;
744 749
@@ -796,10 +801,8 @@ struct net_device *softif_create(const char *name)
796 801
797 soft_iface = alloc_netdev(sizeof(*bat_priv), name, interface_setup); 802 soft_iface = alloc_netdev(sizeof(*bat_priv), name, interface_setup);
798 803
799 if (!soft_iface) { 804 if (!soft_iface)
800 pr_err("Unable to allocate the batman interface: %s\n", name);
801 goto out; 805 goto out;
802 }
803 806
804 ret = register_netdevice(soft_iface); 807 ret = register_netdevice(soft_iface);
805 if (ret < 0) { 808 if (ret < 0) {
@@ -812,6 +815,7 @@ struct net_device *softif_create(const char *name)
812 815
813 atomic_set(&bat_priv->aggregated_ogms, 1); 816 atomic_set(&bat_priv->aggregated_ogms, 1);
814 atomic_set(&bat_priv->bonding, 0); 817 atomic_set(&bat_priv->bonding, 0);
818 atomic_set(&bat_priv->ap_isolation, 0);
815 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); 819 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
816 atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); 820 atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
817 atomic_set(&bat_priv->gw_sel_class, 20); 821 atomic_set(&bat_priv->gw_sel_class, 20);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index fb6931d00cd7..873fb3d8e56f 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -183,7 +183,8 @@ static int tt_local_init(struct bat_priv *bat_priv)
183 return 1; 183 return 1;
184} 184}
185 185
186void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) 186void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
187 int ifindex)
187{ 188{
188 struct bat_priv *bat_priv = netdev_priv(soft_iface); 189 struct bat_priv *bat_priv = netdev_priv(soft_iface);
189 struct tt_local_entry *tt_local_entry = NULL; 190 struct tt_local_entry *tt_local_entry = NULL;
@@ -207,6 +208,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
207 memcpy(tt_local_entry->addr, addr, ETH_ALEN); 208 memcpy(tt_local_entry->addr, addr, ETH_ALEN);
208 tt_local_entry->last_seen = jiffies; 209 tt_local_entry->last_seen = jiffies;
209 tt_local_entry->flags = NO_FLAGS; 210 tt_local_entry->flags = NO_FLAGS;
211 if (is_wifi_iface(ifindex))
212 tt_local_entry->flags |= TT_CLIENT_WIFI;
210 atomic_set(&tt_local_entry->refcount, 2); 213 atomic_set(&tt_local_entry->refcount, 2);
211 214
212 /* the batman interface mac address should never be purged */ 215 /* the batman interface mac address should never be purged */
@@ -329,7 +332,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
329 332
330 rcu_read_lock(); 333 rcu_read_lock();
331 __hlist_for_each_rcu(node, head) 334 __hlist_for_each_rcu(node, head)
332 buf_size += 21; 335 buf_size += 29;
333 rcu_read_unlock(); 336 rcu_read_unlock();
334 } 337 }
335 338
@@ -348,8 +351,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
348 rcu_read_lock(); 351 rcu_read_lock();
349 hlist_for_each_entry_rcu(tt_local_entry, node, 352 hlist_for_each_entry_rcu(tt_local_entry, node,
350 head, hash_entry) { 353 head, hash_entry) {
351 pos += snprintf(buff + pos, 22, " * %pM\n", 354 pos += snprintf(buff + pos, 30, " * %pM "
352 tt_local_entry->addr); 355 "[%c%c%c%c%c]\n",
356 tt_local_entry->addr,
357 (tt_local_entry->flags &
358 TT_CLIENT_ROAM ? 'R' : '.'),
359 (tt_local_entry->flags &
360 TT_CLIENT_NOPURGE ? 'P' : '.'),
361 (tt_local_entry->flags &
362 TT_CLIENT_NEW ? 'N' : '.'),
363 (tt_local_entry->flags &
364 TT_CLIENT_PENDING ? 'X' : '.'),
365 (tt_local_entry->flags &
366 TT_CLIENT_WIFI ? 'W' : '.'));
353 } 367 }
354 rcu_read_unlock(); 368 rcu_read_unlock();
355 } 369 }
@@ -369,8 +383,8 @@ static void tt_local_set_pending(struct bat_priv *bat_priv,
369 tt_local_event(bat_priv, tt_local_entry->addr, 383 tt_local_event(bat_priv, tt_local_entry->addr,
370 tt_local_entry->flags | flags); 384 tt_local_entry->flags | flags);
371 385
372 /* The local client has to be merked as "pending to be removed" but has 386 /* The local client has to be marked as "pending to be removed" but has
373 * to be kept in the table in order to send it in an full tables 387 * to be kept in the table in order to send it in a full table
374 * response issued before the net ttvn increment (consistency check) */ 388 * response issued before the net ttvn increment (consistency check) */
375 tt_local_entry->flags |= TT_CLIENT_PENDING; 389 tt_local_entry->flags |= TT_CLIENT_PENDING;
376} 390}
@@ -495,7 +509,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
495 509
496/* caller must hold orig_node refcount */ 510/* caller must hold orig_node refcount */
497int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, 511int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
498 const unsigned char *tt_addr, uint8_t ttvn, bool roaming) 512 const unsigned char *tt_addr, uint8_t ttvn, bool roaming,
513 bool wifi)
499{ 514{
500 struct tt_global_entry *tt_global_entry; 515 struct tt_global_entry *tt_global_entry;
501 struct orig_node *orig_node_tmp; 516 struct orig_node *orig_node_tmp;
@@ -537,6 +552,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
537 tt_global_entry->roam_at = 0; 552 tt_global_entry->roam_at = 0;
538 } 553 }
539 554
555 if (wifi)
556 tt_global_entry->flags |= TT_CLIENT_WIFI;
557
540 bat_dbg(DBG_TT, bat_priv, 558 bat_dbg(DBG_TT, bat_priv,
541 "Creating new global tt entry: %pM (via %pM)\n", 559 "Creating new global tt entry: %pM (via %pM)\n",
542 tt_global_entry->addr, orig_node->orig); 560 tt_global_entry->addr, orig_node->orig);
@@ -582,8 +600,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
582 seq_printf(seq, 600 seq_printf(seq,
583 "Globally announced TT entries received via the mesh %s\n", 601 "Globally announced TT entries received via the mesh %s\n",
584 net_dev->name); 602 net_dev->name);
585 seq_printf(seq, " %-13s %s %-15s %s\n", 603 seq_printf(seq, " %-13s %s %-15s %s %s\n",
586 "Client", "(TTVN)", "Originator", "(Curr TTVN)"); 604 "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
587 605
588 buf_size = 1; 606 buf_size = 1;
589 /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via 607 /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
@@ -593,7 +611,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
593 611
594 rcu_read_lock(); 612 rcu_read_lock();
595 __hlist_for_each_rcu(node, head) 613 __hlist_for_each_rcu(node, head)
596 buf_size += 59; 614 buf_size += 67;
597 rcu_read_unlock(); 615 rcu_read_unlock();
598 } 616 }
599 617
@@ -612,14 +630,20 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
612 rcu_read_lock(); 630 rcu_read_lock();
613 hlist_for_each_entry_rcu(tt_global_entry, node, 631 hlist_for_each_entry_rcu(tt_global_entry, node,
614 head, hash_entry) { 632 head, hash_entry) {
615 pos += snprintf(buff + pos, 61, 633 pos += snprintf(buff + pos, 69,
616 " * %pM (%3u) via %pM (%3u)\n", 634 " * %pM (%3u) via %pM (%3u) "
617 tt_global_entry->addr, 635 "[%c%c%c]\n", tt_global_entry->addr,
618 tt_global_entry->ttvn, 636 tt_global_entry->ttvn,
619 tt_global_entry->orig_node->orig, 637 tt_global_entry->orig_node->orig,
620 (uint8_t) atomic_read( 638 (uint8_t) atomic_read(
621 &tt_global_entry->orig_node-> 639 &tt_global_entry->orig_node->
622 last_ttvn)); 640 last_ttvn),
641 (tt_global_entry->flags &
642 TT_CLIENT_ROAM ? 'R' : '.'),
643 (tt_global_entry->flags &
644 TT_CLIENT_PENDING ? 'X' : '.'),
645 (tt_global_entry->flags &
646 TT_CLIENT_WIFI ? 'W' : '.'));
623 } 647 }
624 rcu_read_unlock(); 648 rcu_read_unlock();
625 } 649 }
@@ -774,30 +798,56 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
774 bat_priv->tt_global_hash = NULL; 798 bat_priv->tt_global_hash = NULL;
775} 799}
776 800
801static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
802 struct tt_global_entry *tt_global_entry)
803{
804 bool ret = false;
805
806 if (tt_local_entry->flags & TT_CLIENT_WIFI &&
807 tt_global_entry->flags & TT_CLIENT_WIFI)
808 ret = true;
809
810 return ret;
811}
812
777struct orig_node *transtable_search(struct bat_priv *bat_priv, 813struct orig_node *transtable_search(struct bat_priv *bat_priv,
778 const uint8_t *addr) 814 const uint8_t *src, const uint8_t *addr)
779{ 815{
780 struct tt_global_entry *tt_global_entry; 816 struct tt_local_entry *tt_local_entry = NULL;
817 struct tt_global_entry *tt_global_entry = NULL;
781 struct orig_node *orig_node = NULL; 818 struct orig_node *orig_node = NULL;
782 819
783 tt_global_entry = tt_global_hash_find(bat_priv, addr); 820 if (src && atomic_read(&bat_priv->ap_isolation)) {
821 tt_local_entry = tt_local_hash_find(bat_priv, src);
822 if (!tt_local_entry)
823 goto out;
824 }
784 825
826 tt_global_entry = tt_global_hash_find(bat_priv, addr);
785 if (!tt_global_entry) 827 if (!tt_global_entry)
786 goto out; 828 goto out;
787 829
830 /* check whether the clients should not communicate due to AP
831 * isolation */
832 if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry))
833 goto out;
834
788 if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) 835 if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
789 goto free_tt; 836 goto out;
790 837
791 /* A global client marked as PENDING has already moved from that 838 /* A global client marked as PENDING has already moved from that
792 * originator */ 839 * originator */
793 if (tt_global_entry->flags & TT_CLIENT_PENDING) 840 if (tt_global_entry->flags & TT_CLIENT_PENDING)
794 goto free_tt; 841 goto out;
795 842
796 orig_node = tt_global_entry->orig_node; 843 orig_node = tt_global_entry->orig_node;
797 844
798free_tt:
799 tt_global_entry_free_ref(tt_global_entry);
800out: 845out:
846 if (tt_global_entry)
847 tt_global_entry_free_ref(tt_global_entry);
848 if (tt_local_entry)
849 tt_local_entry_free_ref(tt_local_entry);
850
801 return orig_node; 851 return orig_node;
802} 852}
803 853
@@ -999,7 +1049,6 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
999 tt_response = (struct tt_query_packet *)skb_put(skb, 1049 tt_response = (struct tt_query_packet *)skb_put(skb,
1000 tt_query_size + tt_len); 1050 tt_query_size + tt_len);
1001 tt_response->ttvn = ttvn; 1051 tt_response->ttvn = ttvn;
1002 tt_response->tt_data = htons(tt_tot);
1003 1052
1004 tt_change = (struct tt_change *)(skb->data + tt_query_size); 1053 tt_change = (struct tt_change *)(skb->data + tt_query_size);
1005 tt_count = 0; 1054 tt_count = 0;
@@ -1025,12 +1074,17 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1025 } 1074 }
1026 rcu_read_unlock(); 1075 rcu_read_unlock();
1027 1076
1077 /* store in the message the number of entries we have successfully
1078 * copied */
1079 tt_response->tt_data = htons(tt_count);
1080
1028out: 1081out:
1029 return skb; 1082 return skb;
1030} 1083}
1031 1084
1032int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node, 1085static int send_tt_request(struct bat_priv *bat_priv,
1033 uint8_t ttvn, uint16_t tt_crc, bool full_table) 1086 struct orig_node *dst_orig_node,
1087 uint8_t ttvn, uint16_t tt_crc, bool full_table)
1034{ 1088{
1035 struct sk_buff *skb = NULL; 1089 struct sk_buff *skb = NULL;
1036 struct tt_query_packet *tt_request; 1090 struct tt_query_packet *tt_request;
@@ -1137,12 +1191,12 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
1137 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1191 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1138 req_ttvn = tt_request->ttvn; 1192 req_ttvn = tt_request->ttvn;
1139 1193
1140 /* I have not the requested data */ 1194 /* I don't have the requested data */
1141 if (orig_ttvn != req_ttvn || 1195 if (orig_ttvn != req_ttvn ||
1142 tt_request->tt_data != req_dst_orig_node->tt_crc) 1196 tt_request->tt_data != req_dst_orig_node->tt_crc)
1143 goto out; 1197 goto out;
1144 1198
1145 /* If it has explicitly been requested the full table */ 1199 /* If the full table has been explicitly requested */
1146 if (tt_request->flags & TT_FULL_TABLE || 1200 if (tt_request->flags & TT_FULL_TABLE ||
1147 !req_dst_orig_node->tt_buff) 1201 !req_dst_orig_node->tt_buff)
1148 full_table = true; 1202 full_table = true;
@@ -1363,7 +1417,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv,
1363 (tt_change + i)->flags & TT_CLIENT_ROAM); 1417 (tt_change + i)->flags & TT_CLIENT_ROAM);
1364 else 1418 else
1365 if (!tt_global_add(bat_priv, orig_node, 1419 if (!tt_global_add(bat_priv, orig_node,
1366 (tt_change + i)->addr, ttvn, false)) 1420 (tt_change + i)->addr, ttvn, false,
1421 (tt_change + i)->flags &
1422 TT_CLIENT_WIFI))
1367 /* In case of problem while storing a 1423 /* In case of problem while storing a
1368 * global_entry, we stop the updating 1424 * global_entry, we stop the updating
1369 * procedure without committing the 1425 * procedure without committing the
@@ -1403,9 +1459,10 @@ out:
1403 orig_node_free_ref(orig_node); 1459 orig_node_free_ref(orig_node);
1404} 1460}
1405 1461
1406void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node, 1462static void tt_update_changes(struct bat_priv *bat_priv,
1407 uint16_t tt_num_changes, uint8_t ttvn, 1463 struct orig_node *orig_node,
1408 struct tt_change *tt_change) 1464 uint16_t tt_num_changes, uint8_t ttvn,
1465 struct tt_change *tt_change)
1409{ 1466{
1410 _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes, 1467 _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
1411 ttvn); 1468 ttvn);
@@ -1668,6 +1725,8 @@ static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags)
1668 rcu_read_lock(); 1725 rcu_read_lock();
1669 hlist_for_each_entry_rcu(tt_local_entry, node, 1726 hlist_for_each_entry_rcu(tt_local_entry, node,
1670 head, hash_entry) { 1727 head, hash_entry) {
1728 if (!(tt_local_entry->flags & flags))
1729 continue;
1671 tt_local_entry->flags &= ~flags; 1730 tt_local_entry->flags &= ~flags;
1672 atomic_inc(&bat_priv->num_local_tt); 1731 atomic_inc(&bat_priv->num_local_tt);
1673 } 1732 }
@@ -1720,3 +1779,90 @@ void tt_commit_changes(struct bat_priv *bat_priv)
1720 atomic_inc(&bat_priv->ttvn); 1779 atomic_inc(&bat_priv->ttvn);
1721 bat_priv->tt_poss_change = false; 1780 bat_priv->tt_poss_change = false;
1722} 1781}
1782
1783bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
1784{
1785 struct tt_local_entry *tt_local_entry = NULL;
1786 struct tt_global_entry *tt_global_entry = NULL;
1787 bool ret = true;
1788
1789 if (!atomic_read(&bat_priv->ap_isolation))
1790 return false;
1791
1792 tt_local_entry = tt_local_hash_find(bat_priv, dst);
1793 if (!tt_local_entry)
1794 goto out;
1795
1796 tt_global_entry = tt_global_hash_find(bat_priv, src);
1797 if (!tt_global_entry)
1798 goto out;
1799
1800 if (_is_ap_isolated(tt_local_entry, tt_global_entry))
1801 goto out;
1802
1803 ret = false;
1804
1805out:
1806 if (tt_global_entry)
1807 tt_global_entry_free_ref(tt_global_entry);
1808 if (tt_local_entry)
1809 tt_local_entry_free_ref(tt_local_entry);
1810 return ret;
1811}
1812
1813void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
1814 const unsigned char *tt_buff, uint8_t tt_num_changes,
1815 uint8_t ttvn, uint16_t tt_crc)
1816{
1817 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
1818 bool full_table = true;
1819
1820 /* the ttvn increased by one -> we can apply the attached changes */
1821 if (ttvn - orig_ttvn == 1) {
1822 /* the OGM could not contain the changes due to their size or
1823 * because they have already been sent TT_OGM_APPEND_MAX times.
1824 * In this case send a tt request */
1825 if (!tt_num_changes) {
1826 full_table = false;
1827 goto request_table;
1828 }
1829
1830 tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
1831 (struct tt_change *)tt_buff);
1832
1833 /* Even if we received the precomputed crc with the OGM, we
1834 * prefer to recompute it to spot any possible inconsistency
1835 * in the global table */
1836 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
1837
1838 /* The ttvn alone is not enough to guarantee consistency
1839 * because a single value could represent different states
1840 * (due to the wrap around). Thus a node has to check whether
1841 * the resulting table (after applying the changes) is still
1842 * consistent or not. E.g. a node could disconnect while its
1843 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
1844 * checking the CRC value is mandatory to detect the
1845 * inconsistency */
1846 if (orig_node->tt_crc != tt_crc)
1847 goto request_table;
1848
1849 /* Roaming phase is over: tables are in sync again. I can
1850 * unset the flag */
1851 orig_node->tt_poss_change = false;
1852 } else {
1853 /* if we missed more than one change or our tables are not
1854 * in sync anymore -> request fresh tt data */
1855 if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
1856request_table:
1857 bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
1858 "Need to retrieve the correct information "
1859 "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
1860 "%u num_changes: %u)\n", orig_node->orig, ttvn,
1861 orig_ttvn, tt_crc, orig_node->tt_crc,
1862 tt_num_changes);
1863 send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
1864 full_table);
1865 return;
1866 }
1867 }
1868}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index d4122cba53b8..30efd49881a3 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -26,15 +26,16 @@ int tt_len(int changes_num);
26int tt_changes_fill_buffer(struct bat_priv *bat_priv, 26int tt_changes_fill_buffer(struct bat_priv *bat_priv,
27 unsigned char *buff, int buff_len); 27 unsigned char *buff, int buff_len);
28int tt_init(struct bat_priv *bat_priv); 28int tt_init(struct bat_priv *bat_priv);
29void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); 29void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
30 int ifindex);
30void tt_local_remove(struct bat_priv *bat_priv, 31void tt_local_remove(struct bat_priv *bat_priv,
31 const uint8_t *addr, const char *message, bool roaming); 32 const uint8_t *addr, const char *message, bool roaming);
32int tt_local_seq_print_text(struct seq_file *seq, void *offset); 33int tt_local_seq_print_text(struct seq_file *seq, void *offset);
33void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, 34void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
34 const unsigned char *tt_buff, int tt_buff_len); 35 const unsigned char *tt_buff, int tt_buff_len);
35int tt_global_add(struct bat_priv *bat_priv, 36int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
36 struct orig_node *orig_node, const unsigned char *addr, 37 const unsigned char *addr, uint8_t ttvn, bool roaming,
37 uint8_t ttvn, bool roaming); 38 bool wifi);
38int tt_global_seq_print_text(struct seq_file *seq, void *offset); 39int tt_global_seq_print_text(struct seq_file *seq, void *offset);
39void tt_global_del_orig(struct bat_priv *bat_priv, 40void tt_global_del_orig(struct bat_priv *bat_priv,
40 struct orig_node *orig_node, const char *message); 41 struct orig_node *orig_node, const char *message);
@@ -42,25 +43,23 @@ void tt_global_del(struct bat_priv *bat_priv,
42 struct orig_node *orig_node, const unsigned char *addr, 43 struct orig_node *orig_node, const unsigned char *addr,
43 const char *message, bool roaming); 44 const char *message, bool roaming);
44struct orig_node *transtable_search(struct bat_priv *bat_priv, 45struct orig_node *transtable_search(struct bat_priv *bat_priv,
45 const uint8_t *addr); 46 const uint8_t *src, const uint8_t *addr);
46void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, 47void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
47 const unsigned char *tt_buff, uint8_t tt_num_changes); 48 const unsigned char *tt_buff, uint8_t tt_num_changes);
48uint16_t tt_local_crc(struct bat_priv *bat_priv); 49uint16_t tt_local_crc(struct bat_priv *bat_priv);
49uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node); 50uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
50void tt_free(struct bat_priv *bat_priv); 51void tt_free(struct bat_priv *bat_priv);
51int send_tt_request(struct bat_priv *bat_priv,
52 struct orig_node *dst_orig_node, uint8_t hvn,
53 uint16_t tt_crc, bool full_table);
54bool send_tt_response(struct bat_priv *bat_priv, 52bool send_tt_response(struct bat_priv *bat_priv,
55 struct tt_query_packet *tt_request); 53 struct tt_query_packet *tt_request);
56void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
57 uint16_t tt_num_changes, uint8_t ttvn,
58 struct tt_change *tt_change);
59bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); 54bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
60void handle_tt_response(struct bat_priv *bat_priv, 55void handle_tt_response(struct bat_priv *bat_priv,
61 struct tt_query_packet *tt_response); 56 struct tt_query_packet *tt_response);
62void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, 57void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
63 struct orig_node *orig_node); 58 struct orig_node *orig_node);
64void tt_commit_changes(struct bat_priv *bat_priv); 59void tt_commit_changes(struct bat_priv *bat_priv);
60bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
61void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
62 const unsigned char *tt_buff, uint8_t tt_num_changes,
63 uint8_t ttvn, uint16_t tt_crc);
65 64
66#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ 65#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 25bd1db35370..1ae355750511 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -57,7 +57,7 @@ struct hard_iface {
57 * @batman_seqno_reset: time when the batman seqno window was reset 57 * @batman_seqno_reset: time when the batman seqno window was reset
58 * @gw_flags: flags related to gateway class 58 * @gw_flags: flags related to gateway class
59 * @flags: for now only VIS_SERVER flag 59 * @flags: for now only VIS_SERVER flag
60 * @last_real_seqno: last and best known squence number 60 * @last_real_seqno: last and best known sequence number
61 * @last_ttl: ttl of last received packet 61 * @last_ttl: ttl of last received packet
62 * @last_bcast_seqno: last broadcast sequence number received by this host 62 * @last_bcast_seqno: last broadcast sequence number received by this host
63 * 63 *
@@ -146,6 +146,7 @@ struct bat_priv {
146 atomic_t aggregated_ogms; /* boolean */ 146 atomic_t aggregated_ogms; /* boolean */
147 atomic_t bonding; /* boolean */ 147 atomic_t bonding; /* boolean */
148 atomic_t fragmentation; /* boolean */ 148 atomic_t fragmentation; /* boolean */
149 atomic_t ap_isolation; /* boolean */
149 atomic_t vis_mode; /* VIS_TYPE_* */ 150 atomic_t vis_mode; /* VIS_TYPE_* */
150 atomic_t gw_mode; /* GW_MODE_* */ 151 atomic_t gw_mode; /* GW_MODE_* */
151 atomic_t gw_sel_class; /* uint */ 152 atomic_t gw_sel_class; /* uint */
@@ -156,7 +157,7 @@ struct bat_priv {
156 atomic_t bcast_seqno; 157 atomic_t bcast_seqno;
157 atomic_t bcast_queue_left; 158 atomic_t bcast_queue_left;
158 atomic_t batman_queue_left; 159 atomic_t batman_queue_left;
159 atomic_t ttvn; /* tranlation table version number */ 160 atomic_t ttvn; /* translation table version number */
160 atomic_t tt_ogm_append_cnt; 161 atomic_t tt_ogm_append_cnt;
161 atomic_t tt_local_changes; /* changes registered in a OGM interval */ 162 atomic_t tt_local_changes; /* changes registered in a OGM interval */
162 /* The tt_poss_change flag is used to detect an ongoing roaming phase. 163 /* The tt_poss_change flag is used to detect an ongoing roaming phase.
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 32b125fb3d3b..07d1c1da89dd 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
299 goto find_router; 299 goto find_router;
300 } 300 }
301 301
302 /* check for tt host - increases orig_node refcount */ 302 /* check for tt host - increases orig_node refcount.
303 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 303 * returns NULL in case of AP isolation */
304 orig_node = transtable_search(bat_priv, ethhdr->h_source,
305 ethhdr->h_dest);
304 306
305find_router: 307find_router:
306 /** 308 /**
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
index 62f54b954625..8fd5535544b9 100644
--- a/net/batman-adv/unicast.h
+++ b/net/batman-adv/unicast.h
@@ -24,7 +24,7 @@
24 24
25#include "packet.h" 25#include "packet.h"
26 26
27#define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */ 27#define FRAG_TIMEOUT 10000 /* purge frag list entries after time in ms */
28#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ 28#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
29 29
30int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, 30int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 8a1b98589d76..f81a6b668b0c 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -131,7 +131,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
131 return; 131 return;
132 } 132 }
133 133
134 /* its a new address, add it to the list */ 134 /* it's a new address, add it to the list */
135 entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 135 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
136 if (!entry) 136 if (!entry)
137 return; 137 return;
@@ -465,7 +465,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
465 /* try to add it */ 465 /* try to add it */
466 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 466 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
467 info, &info->hash_entry); 467 info, &info->hash_entry);
468 if (hash_added < 0) { 468 if (hash_added != 0) {
469 /* did not work (for some reason) */ 469 /* did not work (for some reason) */
470 kref_put(&info->refcount, free_info); 470 kref_put(&info->refcount, free_info);
471 info = NULL; 471 info = NULL;
@@ -887,10 +887,8 @@ int vis_init(struct bat_priv *bat_priv)
887 } 887 }
888 888
889 bat_priv->my_vis_info = kmalloc(MAX_VIS_PACKET_SIZE, GFP_ATOMIC); 889 bat_priv->my_vis_info = kmalloc(MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
890 if (!bat_priv->my_vis_info) { 890 if (!bat_priv->my_vis_info)
891 pr_err("Can't initialize vis packet\n");
892 goto err; 891 goto err;
893 }
894 892
895 bat_priv->my_vis_info->skb_packet = dev_alloc_skb(sizeof(*packet) + 893 bat_priv->my_vis_info->skb_packet = dev_alloc_skb(sizeof(*packet) +
896 MAX_VIS_PACKET_SIZE + 894 MAX_VIS_PACKET_SIZE +
@@ -920,7 +918,7 @@ int vis_init(struct bat_priv *bat_priv)
920 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 918 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
921 bat_priv->my_vis_info, 919 bat_priv->my_vis_info,
922 &bat_priv->my_vis_info->hash_entry); 920 &bat_priv->my_vis_info->hash_entry);
923 if (hash_added < 0) { 921 if (hash_added != 0) {
924 pr_err("Can't add own vis packet into hash\n"); 922 pr_err("Can't add own vis packet into hash\n");
925 /* not in hash, need to remove it manually. */ 923 /* not in hash, need to remove it manually. */
926 kref_put(&bat_priv->my_vis_info->refcount, free_info); 924 kref_put(&bat_priv->my_vis_info->refcount, free_info);