Blame view
net/batman-adv/hard-interface.c
16.5 KB
c6c8fea29 net: Add batman-a... |
1 |
/* |
64afe3539 batman-adv: Updat... |
2 |
* Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: |
c6c8fea29 net: Add batman-a... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
* * Marek Lindner, Simon Wunderlich * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA * */ #include "main.h" #include "hard-interface.h" #include "soft-interface.h" #include "send.h" #include "translation-table.h" #include "routing.h" #include "bat_sysfs.h" #include "originator.h" #include "hash.h" |
d0b9fd89c batman-adv: move ... |
31 |
#include "bat_ogm.h" |
c6c8fea29 net: Add batman-a... |
32 33 |
#include <linux/if_arp.h> |
fb86d7648 batman-adv: Remov... |
34 35 36 37 38 |
static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev); |
ed75ccbe2 batman-adv: Corre... |
39 |
void hardif_free_rcu(struct rcu_head *rcu) |
c6c8fea29 net: Add batman-a... |
40 |
{ |
e6c10f433 batman-adv: renam... |
41 |
struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
42 |
|
e6c10f433 batman-adv: renam... |
43 44 45 |
hard_iface = container_of(rcu, struct hard_iface, rcu); dev_put(hard_iface->net_dev); kfree(hard_iface); |
c6c8fea29 net: Add batman-a... |
46 |
} |
747e4221a batman-adv: Add c... |
47 |
struct hard_iface *hardif_get_by_netdev(const struct net_device *net_dev) |
c6c8fea29 net: Add batman-a... |
48 |
{ |
e6c10f433 batman-adv: renam... |
49 |
struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
50 51 |
rcu_read_lock(); |
e6c10f433 batman-adv: renam... |
52 53 54 |
list_for_each_entry_rcu(hard_iface, &hardif_list, list) { if (hard_iface->net_dev == net_dev && atomic_inc_not_zero(&hard_iface->refcount)) |
c6c8fea29 net: Add batman-a... |
55 56 |
goto out; } |
e6c10f433 batman-adv: renam... |
57 |
hard_iface = NULL; |
c6c8fea29 net: Add batman-a... |
58 59 |
out: |
c6c8fea29 net: Add batman-a... |
60 |
rcu_read_unlock(); |
e6c10f433 batman-adv: renam... |
61 |
return hard_iface; |
c6c8fea29 net: Add batman-a... |
62 |
} |
747e4221a batman-adv: Add c... |
63 |
static int is_valid_iface(const struct net_device *net_dev) |
c6c8fea29 net: Add batman-a... |
64 65 66 67 68 69 70 71 72 73 74 |
{ if (net_dev->flags & IFF_LOOPBACK) return 0; if (net_dev->type != ARPHRD_ETHER) return 0; if (net_dev->addr_len != ETH_ALEN) return 0; /* no batman over batman */ |
e44d8fe2b batman-adv: Disal... |
75 |
if (softif_is_valid(net_dev)) |
c6c8fea29 net: Add batman-a... |
76 |
return 0; |
c6c8fea29 net: Add batman-a... |
77 78 79 80 81 82 83 |
/* Device is being bridged */ /* if (net_dev->priv_flags & IFF_BRIDGE_PORT) return 0; */ return 1; } |
747e4221a batman-adv: Add c... |
84 |
static struct hard_iface *hardif_get_active(const struct net_device *soft_iface) |
c6c8fea29 net: Add batman-a... |
85 |
{ |
e6c10f433 batman-adv: renam... |
86 |
struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
87 88 |
rcu_read_lock(); |
e6c10f433 batman-adv: renam... |
89 90 |
list_for_each_entry_rcu(hard_iface, &hardif_list, list) { if (hard_iface->soft_iface != soft_iface) |
c6c8fea29 net: Add batman-a... |
91 |
continue; |
e6c10f433 batman-adv: renam... |
92 93 |
if (hard_iface->if_status == IF_ACTIVE && atomic_inc_not_zero(&hard_iface->refcount)) |
c6c8fea29 net: Add batman-a... |
94 95 |
goto out; } |
e6c10f433 batman-adv: renam... |
96 |
hard_iface = NULL; |
c6c8fea29 net: Add batman-a... |
97 98 |
out: |
c6c8fea29 net: Add batman-a... |
99 |
rcu_read_unlock(); |
e6c10f433 batman-adv: renam... |
100 |
return hard_iface; |
c6c8fea29 net: Add batman-a... |
101 |
} |
32ae9b221 batman-adv: Make ... |
102 |
static void primary_if_update_addr(struct bat_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
103 104 |
{ struct vis_packet *vis_packet; |
32ae9b221 batman-adv: Make ... |
105 106 107 108 109 |
struct hard_iface *primary_if; primary_if = primary_if_get_selected(bat_priv); if (!primary_if) goto out; |
c6c8fea29 net: Add batman-a... |
110 111 112 |
vis_packet = (struct vis_packet *) bat_priv->my_vis_info->skb_packet->data; |
32ae9b221 batman-adv: Make ... |
113 |
memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
c6c8fea29 net: Add batman-a... |
114 |
memcpy(vis_packet->sender_orig, |
32ae9b221 batman-adv: Make ... |
115 116 117 118 119 |
primary_if->net_dev->dev_addr, ETH_ALEN); out: if (primary_if) hardif_free_ref(primary_if); |
c6c8fea29 net: Add batman-a... |
120 |
} |
32ae9b221 batman-adv: Make ... |
121 122 |
static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *new_hard_iface) |
c6c8fea29 net: Add batman-a... |
123 |
{ |
32ae9b221 batman-adv: Make ... |
124 |
struct hard_iface *curr_hard_iface; |
c6c8fea29 net: Add batman-a... |
125 |
|
c3caf5196 batman-adv: Remov... |
126 |
ASSERT_RTNL(); |
c6c8fea29 net: Add batman-a... |
127 |
|
32ae9b221 batman-adv: Make ... |
128 129 |
if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) new_hard_iface = NULL; |
c6c8fea29 net: Add batman-a... |
130 |
|
728cbc6ac batman-adv: Use r... |
131 |
curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); |
32ae9b221 batman-adv: Make ... |
132 |
rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); |
c6c8fea29 net: Add batman-a... |
133 |
|
32ae9b221 batman-adv: Make ... |
134 135 |
if (curr_hard_iface) hardif_free_ref(curr_hard_iface); |
c6c8fea29 net: Add batman-a... |
136 |
|
32ae9b221 batman-adv: Make ... |
137 |
if (!new_hard_iface) |
c3caf5196 batman-adv: Remov... |
138 |
return; |
32ae9b221 batman-adv: Make ... |
139 |
|
d0b9fd89c batman-adv: move ... |
140 |
bat_ogm_init_primary(new_hard_iface); |
32ae9b221 batman-adv: Make ... |
141 |
primary_if_update_addr(bat_priv); |
c6c8fea29 net: Add batman-a... |
142 |
} |
747e4221a batman-adv: Add c... |
143 |
static bool hardif_is_iface_up(const struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
144 |
{ |
e6c10f433 batman-adv: renam... |
145 |
if (hard_iface->net_dev->flags & IFF_UP) |
c6c8fea29 net: Add batman-a... |
146 147 148 149 |
return true; return false; } |
747e4221a batman-adv: Add c... |
150 |
static void check_known_mac_addr(const struct net_device *net_dev) |
c6c8fea29 net: Add batman-a... |
151 |
{ |
747e4221a batman-adv: Add c... |
152 |
const struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
153 154 |
rcu_read_lock(); |
e6c10f433 batman-adv: renam... |
155 156 157 |
list_for_each_entry_rcu(hard_iface, &hardif_list, list) { if ((hard_iface->if_status != IF_ACTIVE) && (hard_iface->if_status != IF_TO_BE_ACTIVATED)) |
c6c8fea29 net: Add batman-a... |
158 |
continue; |
e6c10f433 batman-adv: renam... |
159 |
if (hard_iface->net_dev == net_dev) |
c6c8fea29 net: Add batman-a... |
160 |
continue; |
e6c10f433 batman-adv: renam... |
161 162 |
if (!compare_eth(hard_iface->net_dev->dev_addr, net_dev->dev_addr)) |
c6c8fea29 net: Add batman-a... |
163 164 165 166 167 |
continue; pr_warning("The newly added mac address (%pM) already exists " "on: %s ", net_dev->dev_addr, |
e6c10f433 batman-adv: renam... |
168 |
hard_iface->net_dev->name); |
c6c8fea29 net: Add batman-a... |
169 170 171 172 173 174 175 176 177 |
pr_warning("It is strongly recommended to keep mac addresses " "unique to avoid problems! "); } rcu_read_unlock(); } int hardif_min_mtu(struct net_device *soft_iface) { |
747e4221a batman-adv: Add c... |
178 179 |
const struct bat_priv *bat_priv = netdev_priv(soft_iface); const struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
180 181 182 183 184 185 186 187 |
/* allow big frames if all devices are capable to do so * (have MTU > 1500 + BAT_HEADER_LEN) */ int min_mtu = ETH_DATA_LEN; if (atomic_read(&bat_priv->fragmentation)) goto out; rcu_read_lock(); |
e6c10f433 batman-adv: renam... |
188 189 190 |
list_for_each_entry_rcu(hard_iface, &hardif_list, list) { if ((hard_iface->if_status != IF_ACTIVE) && (hard_iface->if_status != IF_TO_BE_ACTIVATED)) |
c6c8fea29 net: Add batman-a... |
191 |
continue; |
e6c10f433 batman-adv: renam... |
192 |
if (hard_iface->soft_iface != soft_iface) |
c6c8fea29 net: Add batman-a... |
193 |
continue; |
e6c10f433 batman-adv: renam... |
194 |
min_mtu = min_t(int, hard_iface->net_dev->mtu - BAT_HEADER_LEN, |
c6c8fea29 net: Add batman-a... |
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
min_mtu); } rcu_read_unlock(); out: return min_mtu; } /* adjusts the MTU if a new interface with a smaller MTU appeared. */ void update_min_mtu(struct net_device *soft_iface) { int min_mtu; min_mtu = hardif_min_mtu(soft_iface); if (soft_iface->mtu != min_mtu) soft_iface->mtu = min_mtu; } |
e6c10f433 batman-adv: renam... |
211 |
static void hardif_activate_interface(struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
212 213 |
{ struct bat_priv *bat_priv; |
32ae9b221 batman-adv: Make ... |
214 |
struct hard_iface *primary_if = NULL; |
c6c8fea29 net: Add batman-a... |
215 |
|
e6c10f433 batman-adv: renam... |
216 |
if (hard_iface->if_status != IF_INACTIVE) |
32ae9b221 batman-adv: Make ... |
217 |
goto out; |
c6c8fea29 net: Add batman-a... |
218 |
|
e6c10f433 batman-adv: renam... |
219 |
bat_priv = netdev_priv(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
220 |
|
d0b9fd89c batman-adv: move ... |
221 |
bat_ogm_update_mac(hard_iface); |
e6c10f433 batman-adv: renam... |
222 |
hard_iface->if_status = IF_TO_BE_ACTIVATED; |
c6c8fea29 net: Add batman-a... |
223 224 225 |
/** * the first active interface becomes our primary interface or |
015758d00 batman-adv: corre... |
226 |
* the next active interface after the old primary interface was removed |
c6c8fea29 net: Add batman-a... |
227 |
*/ |
32ae9b221 batman-adv: Make ... |
228 229 230 |
primary_if = primary_if_get_selected(bat_priv); if (!primary_if) primary_if_select(bat_priv, hard_iface); |
c6c8fea29 net: Add batman-a... |
231 |
|
e6c10f433 batman-adv: renam... |
232 233 234 |
bat_info(hard_iface->soft_iface, "Interface activated: %s ", hard_iface->net_dev->name); |
c6c8fea29 net: Add batman-a... |
235 |
|
e6c10f433 batman-adv: renam... |
236 |
update_min_mtu(hard_iface->soft_iface); |
32ae9b221 batman-adv: Make ... |
237 238 239 240 |
out: if (primary_if) hardif_free_ref(primary_if); |
c6c8fea29 net: Add batman-a... |
241 |
} |
e6c10f433 batman-adv: renam... |
242 |
static void hardif_deactivate_interface(struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
243 |
{ |
e6c10f433 batman-adv: renam... |
244 245 |
if ((hard_iface->if_status != IF_ACTIVE) && (hard_iface->if_status != IF_TO_BE_ACTIVATED)) |
c6c8fea29 net: Add batman-a... |
246 |
return; |
e6c10f433 batman-adv: renam... |
247 |
hard_iface->if_status = IF_INACTIVE; |
c6c8fea29 net: Add batman-a... |
248 |
|
e6c10f433 batman-adv: renam... |
249 250 251 |
bat_info(hard_iface->soft_iface, "Interface deactivated: %s ", hard_iface->net_dev->name); |
c6c8fea29 net: Add batman-a... |
252 |
|
e6c10f433 batman-adv: renam... |
253 |
update_min_mtu(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
254 |
} |
747e4221a batman-adv: Add c... |
255 256 |
int hardif_enable_interface(struct hard_iface *hard_iface, const char *iface_name) |
c6c8fea29 net: Add batman-a... |
257 258 |
{ struct bat_priv *bat_priv; |
e44d8fe2b batman-adv: Disal... |
259 260 |
struct net_device *soft_iface; int ret; |
c6c8fea29 net: Add batman-a... |
261 |
|
e6c10f433 batman-adv: renam... |
262 |
if (hard_iface->if_status != IF_NOT_IN_USE) |
c6c8fea29 net: Add batman-a... |
263 |
goto out; |
e6c10f433 batman-adv: renam... |
264 |
if (!atomic_inc_not_zero(&hard_iface->refcount)) |
ed75ccbe2 batman-adv: Corre... |
265 |
goto out; |
e44d8fe2b batman-adv: Disal... |
266 |
soft_iface = dev_get_by_name(&init_net, iface_name); |
c6c8fea29 net: Add batman-a... |
267 |
|
e44d8fe2b batman-adv: Disal... |
268 269 |
if (!soft_iface) { soft_iface = softif_create(iface_name); |
c6c8fea29 net: Add batman-a... |
270 |
|
e44d8fe2b batman-adv: Disal... |
271 272 |
if (!soft_iface) { ret = -ENOMEM; |
c6c8fea29 net: Add batman-a... |
273 |
goto err; |
e44d8fe2b batman-adv: Disal... |
274 |
} |
c6c8fea29 net: Add batman-a... |
275 276 |
/* dev_get_by_name() increases the reference counter for us */ |
e44d8fe2b batman-adv: Disal... |
277 278 279 280 281 282 283 284 285 286 287 |
dev_hold(soft_iface); } if (!softif_is_valid(soft_iface)) { pr_err("Can't create batman mesh interface %s: " "already exists as regular interface ", soft_iface->name); dev_put(soft_iface); ret = -EINVAL; goto err; |
c6c8fea29 net: Add batman-a... |
288 |
} |
e44d8fe2b batman-adv: Disal... |
289 |
hard_iface->soft_iface = soft_iface; |
e6c10f433 batman-adv: renam... |
290 |
bat_priv = netdev_priv(hard_iface->soft_iface); |
d0b9fd89c batman-adv: move ... |
291 292 |
bat_ogm_init(hard_iface); |
c6c8fea29 net: Add batman-a... |
293 |
|
e6c10f433 batman-adv: renam... |
294 295 296 297 |
if (!hard_iface->packet_buff) { bat_err(hard_iface->soft_iface, "Can't add interface packet " "(%s): out of memory ", hard_iface->net_dev->name); |
e44d8fe2b batman-adv: Disal... |
298 |
ret = -ENOMEM; |
c6c8fea29 net: Add batman-a... |
299 300 |
goto err; } |
e6c10f433 batman-adv: renam... |
301 |
hard_iface->if_num = bat_priv->num_ifaces; |
c6c8fea29 net: Add batman-a... |
302 |
bat_priv->num_ifaces++; |
e6c10f433 batman-adv: renam... |
303 304 |
hard_iface->if_status = IF_INACTIVE; orig_hash_add_if(hard_iface, bat_priv->num_ifaces); |
c6c8fea29 net: Add batman-a... |
305 |
|
e6c10f433 batman-adv: renam... |
306 307 308 309 |
hard_iface->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN); hard_iface->batman_adv_ptype.func = batman_skb_recv; hard_iface->batman_adv_ptype.dev = hard_iface->net_dev; dev_add_pack(&hard_iface->batman_adv_ptype); |
c6c8fea29 net: Add batman-a... |
310 |
|
e6c10f433 batman-adv: renam... |
311 312 313 314 315 |
atomic_set(&hard_iface->seqno, 1); atomic_set(&hard_iface->frag_seqno, 1); bat_info(hard_iface->soft_iface, "Adding interface: %s ", hard_iface->net_dev->name); |
c6c8fea29 net: Add batman-a... |
316 |
|
e6c10f433 batman-adv: renam... |
317 |
if (atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu < |
c6c8fea29 net: Add batman-a... |
318 |
ETH_DATA_LEN + BAT_HEADER_LEN) |
e6c10f433 batman-adv: renam... |
319 |
bat_info(hard_iface->soft_iface, |
c6c8fea29 net: Add batman-a... |
320 321 322 323 324 325 |
"The MTU of interface %s is too small (%i) to handle " "the transport of batman-adv packets. Packets going " "over this interface will be fragmented on layer2 " "which could impact the performance. Setting the MTU " "to %zi would solve the problem. ", |
e6c10f433 batman-adv: renam... |
326 |
hard_iface->net_dev->name, hard_iface->net_dev->mtu, |
c6c8fea29 net: Add batman-a... |
327 |
ETH_DATA_LEN + BAT_HEADER_LEN); |
e6c10f433 batman-adv: renam... |
328 |
if (!atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu < |
c6c8fea29 net: Add batman-a... |
329 |
ETH_DATA_LEN + BAT_HEADER_LEN) |
e6c10f433 batman-adv: renam... |
330 |
bat_info(hard_iface->soft_iface, |
c6c8fea29 net: Add batman-a... |
331 332 333 334 335 |
"The MTU of interface %s is too small (%i) to handle " "the transport of batman-adv packets. If you experience" " problems getting traffic through try increasing the " "MTU to %zi. ", |
e6c10f433 batman-adv: renam... |
336 |
hard_iface->net_dev->name, hard_iface->net_dev->mtu, |
c6c8fea29 net: Add batman-a... |
337 |
ETH_DATA_LEN + BAT_HEADER_LEN); |
e6c10f433 batman-adv: renam... |
338 339 |
if (hardif_is_iface_up(hard_iface)) hardif_activate_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
340 |
else |
e6c10f433 batman-adv: renam... |
341 |
bat_err(hard_iface->soft_iface, "Not using interface %s " |
c6c8fea29 net: Add batman-a... |
342 343 |
"(retrying later): interface not active ", |
e6c10f433 batman-adv: renam... |
344 |
hard_iface->net_dev->name); |
c6c8fea29 net: Add batman-a... |
345 346 |
/* begin scheduling originator messages on that interface */ |
b9dacc521 batman-adv: agglo... |
347 |
schedule_bat_ogm(hard_iface); |
c6c8fea29 net: Add batman-a... |
348 349 350 351 352 |
out: return 0; err: |
e6c10f433 batman-adv: renam... |
353 |
hardif_free_ref(hard_iface); |
e44d8fe2b batman-adv: Disal... |
354 |
return ret; |
c6c8fea29 net: Add batman-a... |
355 |
} |
e6c10f433 batman-adv: renam... |
356 |
void hardif_disable_interface(struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
357 |
{ |
e6c10f433 batman-adv: renam... |
358 |
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
32ae9b221 batman-adv: Make ... |
359 |
struct hard_iface *primary_if = NULL; |
c6c8fea29 net: Add batman-a... |
360 |
|
e6c10f433 batman-adv: renam... |
361 362 |
if (hard_iface->if_status == IF_ACTIVE) hardif_deactivate_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
363 |
|
e6c10f433 batman-adv: renam... |
364 |
if (hard_iface->if_status != IF_INACTIVE) |
32ae9b221 batman-adv: Make ... |
365 |
goto out; |
c6c8fea29 net: Add batman-a... |
366 |
|
e6c10f433 batman-adv: renam... |
367 368 369 370 |
bat_info(hard_iface->soft_iface, "Removing interface: %s ", hard_iface->net_dev->name); dev_remove_pack(&hard_iface->batman_adv_ptype); |
c6c8fea29 net: Add batman-a... |
371 372 |
bat_priv->num_ifaces--; |
e6c10f433 batman-adv: renam... |
373 |
orig_hash_del_if(hard_iface, bat_priv->num_ifaces); |
c6c8fea29 net: Add batman-a... |
374 |
|
32ae9b221 batman-adv: Make ... |
375 376 |
primary_if = primary_if_get_selected(bat_priv); if (hard_iface == primary_if) { |
e6c10f433 batman-adv: renam... |
377 |
struct hard_iface *new_if; |
c6c8fea29 net: Add batman-a... |
378 |
|
e6c10f433 batman-adv: renam... |
379 |
new_if = hardif_get_active(hard_iface->soft_iface); |
32ae9b221 batman-adv: Make ... |
380 |
primary_if_select(bat_priv, new_if); |
c6c8fea29 net: Add batman-a... |
381 382 |
if (new_if) |
ed75ccbe2 batman-adv: Corre... |
383 |
hardif_free_ref(new_if); |
c6c8fea29 net: Add batman-a... |
384 |
} |
e6c10f433 batman-adv: renam... |
385 386 387 |
kfree(hard_iface->packet_buff); hard_iface->packet_buff = NULL; hard_iface->if_status = IF_NOT_IN_USE; |
c6c8fea29 net: Add batman-a... |
388 |
|
e6c10f433 batman-adv: renam... |
389 |
/* delete all references to this hard_iface */ |
c6c8fea29 net: Add batman-a... |
390 |
purge_orig_ref(bat_priv); |
e6c10f433 batman-adv: renam... |
391 392 |
purge_outstanding_packets(bat_priv, hard_iface); dev_put(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
393 394 395 |
/* nobody uses this interface anymore */ if (!bat_priv->num_ifaces) |
e6c10f433 batman-adv: renam... |
396 |
softif_destroy(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
397 |
|
e6c10f433 batman-adv: renam... |
398 399 |
hard_iface->soft_iface = NULL; hardif_free_ref(hard_iface); |
32ae9b221 batman-adv: Make ... |
400 401 402 403 |
out: if (primary_if) hardif_free_ref(primary_if); |
c6c8fea29 net: Add batman-a... |
404 |
} |
e6c10f433 batman-adv: renam... |
405 |
static struct hard_iface *hardif_add_interface(struct net_device *net_dev) |
c6c8fea29 net: Add batman-a... |
406 |
{ |
e6c10f433 batman-adv: renam... |
407 |
struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
408 |
int ret; |
c3caf5196 batman-adv: Remov... |
409 |
ASSERT_RTNL(); |
c6c8fea29 net: Add batman-a... |
410 411 412 413 414 |
ret = is_valid_iface(net_dev); if (ret != 1) goto out; dev_hold(net_dev); |
704509b8d batman-adv: Calcu... |
415 |
hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC); |
320f422f6 batman-adv: Remov... |
416 |
if (!hard_iface) |
c6c8fea29 net: Add batman-a... |
417 |
goto release_dev; |
c6c8fea29 net: Add batman-a... |
418 |
|
e6c10f433 batman-adv: renam... |
419 |
ret = sysfs_add_hardif(&hard_iface->hardif_obj, net_dev); |
c6c8fea29 net: Add batman-a... |
420 421 |
if (ret) goto free_if; |
e6c10f433 batman-adv: renam... |
422 423 424 425 426 |
hard_iface->if_num = -1; hard_iface->net_dev = net_dev; hard_iface->soft_iface = NULL; hard_iface->if_status = IF_NOT_IN_USE; INIT_LIST_HEAD(&hard_iface->list); |
ed75ccbe2 batman-adv: Corre... |
427 |
/* extra reference for return */ |
e6c10f433 batman-adv: renam... |
428 |
atomic_set(&hard_iface->refcount, 2); |
c6c8fea29 net: Add batman-a... |
429 |
|
e6c10f433 batman-adv: renam... |
430 |
check_known_mac_addr(hard_iface->net_dev); |
e6c10f433 batman-adv: renam... |
431 |
list_add_tail_rcu(&hard_iface->list, &hardif_list); |
c6c8fea29 net: Add batman-a... |
432 |
|
e6c10f433 batman-adv: renam... |
433 |
return hard_iface; |
c6c8fea29 net: Add batman-a... |
434 435 |
free_if: |
e6c10f433 batman-adv: renam... |
436 |
kfree(hard_iface); |
c6c8fea29 net: Add batman-a... |
437 438 439 440 441 |
release_dev: dev_put(net_dev); out: return NULL; } |
e6c10f433 batman-adv: renam... |
442 |
static void hardif_remove_interface(struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
443 |
{ |
c3caf5196 batman-adv: Remov... |
444 |
ASSERT_RTNL(); |
c6c8fea29 net: Add batman-a... |
445 |
/* first deactivate interface */ |
e6c10f433 batman-adv: renam... |
446 447 |
if (hard_iface->if_status != IF_NOT_IN_USE) hardif_disable_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
448 |
|
e6c10f433 batman-adv: renam... |
449 |
if (hard_iface->if_status != IF_NOT_IN_USE) |
c6c8fea29 net: Add batman-a... |
450 |
return; |
e6c10f433 batman-adv: renam... |
451 452 453 |
hard_iface->if_status = IF_TO_BE_REMOVED; sysfs_del_hardif(&hard_iface->hardif_obj); hardif_free_ref(hard_iface); |
c6c8fea29 net: Add batman-a... |
454 455 456 457 |
} void hardif_remove_interfaces(void) { |
e6c10f433 batman-adv: renam... |
458 |
struct hard_iface *hard_iface, *hard_iface_tmp; |
c6c8fea29 net: Add batman-a... |
459 |
|
c3caf5196 batman-adv: Remov... |
460 |
rtnl_lock(); |
e6c10f433 batman-adv: renam... |
461 462 463 |
list_for_each_entry_safe(hard_iface, hard_iface_tmp, &hardif_list, list) { list_del_rcu(&hard_iface->list); |
e6c10f433 batman-adv: renam... |
464 |
hardif_remove_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
465 466 467 468 469 470 471 |
} rtnl_unlock(); } static int hard_if_event(struct notifier_block *this, unsigned long event, void *ptr) { |
5f718c200 batman-adv: Remov... |
472 |
struct net_device *net_dev = ptr; |
e6c10f433 batman-adv: renam... |
473 |
struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); |
32ae9b221 batman-adv: Make ... |
474 |
struct hard_iface *primary_if = NULL; |
c6c8fea29 net: Add batman-a... |
475 |
struct bat_priv *bat_priv; |
e6c10f433 batman-adv: renam... |
476 477 |
if (!hard_iface && event == NETDEV_REGISTER) hard_iface = hardif_add_interface(net_dev); |
c6c8fea29 net: Add batman-a... |
478 |
|
e6c10f433 batman-adv: renam... |
479 |
if (!hard_iface) |
c6c8fea29 net: Add batman-a... |
480 481 482 483 |
goto out; switch (event) { case NETDEV_UP: |
e6c10f433 batman-adv: renam... |
484 |
hardif_activate_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
485 486 487 |
break; case NETDEV_GOING_DOWN: case NETDEV_DOWN: |
e6c10f433 batman-adv: renam... |
488 |
hardif_deactivate_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
489 490 |
break; case NETDEV_UNREGISTER: |
e6c10f433 batman-adv: renam... |
491 |
list_del_rcu(&hard_iface->list); |
c6c8fea29 net: Add batman-a... |
492 |
|
e6c10f433 batman-adv: renam... |
493 |
hardif_remove_interface(hard_iface); |
c6c8fea29 net: Add batman-a... |
494 495 |
break; case NETDEV_CHANGEMTU: |
e6c10f433 batman-adv: renam... |
496 497 |
if (hard_iface->soft_iface) update_min_mtu(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
498 499 |
break; case NETDEV_CHANGEADDR: |
e6c10f433 batman-adv: renam... |
500 |
if (hard_iface->if_status == IF_NOT_IN_USE) |
c6c8fea29 net: Add batman-a... |
501 |
goto hardif_put; |
e6c10f433 batman-adv: renam... |
502 |
check_known_mac_addr(hard_iface->net_dev); |
d0b9fd89c batman-adv: move ... |
503 |
bat_ogm_update_mac(hard_iface); |
c6c8fea29 net: Add batman-a... |
504 |
|
e6c10f433 batman-adv: renam... |
505 |
bat_priv = netdev_priv(hard_iface->soft_iface); |
32ae9b221 batman-adv: Make ... |
506 507 508 509 510 511 |
primary_if = primary_if_get_selected(bat_priv); if (!primary_if) goto hardif_put; if (hard_iface == primary_if) primary_if_update_addr(bat_priv); |
c6c8fea29 net: Add batman-a... |
512 513 514 |
break; default: break; |
f81c62242 net: Remove unnec... |
515 |
} |
c6c8fea29 net: Add batman-a... |
516 517 |
hardif_put: |
e6c10f433 batman-adv: renam... |
518 |
hardif_free_ref(hard_iface); |
c6c8fea29 net: Add batman-a... |
519 |
out: |
32ae9b221 batman-adv: Make ... |
520 521 |
if (primary_if) hardif_free_ref(primary_if); |
c6c8fea29 net: Add batman-a... |
522 523 |
return NOTIFY_DONE; } |
015758d00 batman-adv: corre... |
524 |
/* incoming packets with the batman ethertype received on any active hard |
c6c8fea29 net: Add batman-a... |
525 |
* interface */ |
fb86d7648 batman-adv: Remov... |
526 527 528 |
static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) |
c6c8fea29 net: Add batman-a... |
529 530 |
{ struct bat_priv *bat_priv; |
b6da4bf5d batman-adv: renam... |
531 |
struct batman_ogm_packet *batman_ogm_packet; |
e6c10f433 batman-adv: renam... |
532 |
struct hard_iface *hard_iface; |
c6c8fea29 net: Add batman-a... |
533 |
int ret; |
e6c10f433 batman-adv: renam... |
534 |
hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype); |
c6c8fea29 net: Add batman-a... |
535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
skb = skb_share_check(skb, GFP_ATOMIC); /* skb was released by skb_share_check() */ if (!skb) goto err_out; /* packet should hold at least type and version */ if (unlikely(!pskb_may_pull(skb, 2))) goto err_free; /* expect a valid ethernet header here. */ if (unlikely(skb->mac_len != sizeof(struct ethhdr) || !skb_mac_header(skb))) goto err_free; |
e6c10f433 batman-adv: renam... |
549 |
if (!hard_iface->soft_iface) |
c6c8fea29 net: Add batman-a... |
550 |
goto err_free; |
e6c10f433 batman-adv: renam... |
551 |
bat_priv = netdev_priv(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
552 553 554 555 556 |
if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto err_free; /* discard frames on not active interfaces */ |
e6c10f433 batman-adv: renam... |
557 |
if (hard_iface->if_status != IF_ACTIVE) |
c6c8fea29 net: Add batman-a... |
558 |
goto err_free; |
b6da4bf5d batman-adv: renam... |
559 |
batman_ogm_packet = (struct batman_ogm_packet *)skb->data; |
c6c8fea29 net: Add batman-a... |
560 |
|
b6da4bf5d batman-adv: renam... |
561 |
if (batman_ogm_packet->version != COMPAT_VERSION) { |
c6c8fea29 net: Add batman-a... |
562 563 564 |
bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: incompatible batman version (%i) ", |
b6da4bf5d batman-adv: renam... |
565 |
batman_ogm_packet->version); |
c6c8fea29 net: Add batman-a... |
566 567 568 569 570 |
goto err_free; } /* all receive handlers return whether they received or reused * the supplied skb. if not, we have to free the skb. */ |
b6da4bf5d batman-adv: renam... |
571 |
switch (batman_ogm_packet->packet_type) { |
c6c8fea29 net: Add batman-a... |
572 |
/* batman originator packet */ |
b6da4bf5d batman-adv: renam... |
573 |
case BAT_OGM: |
fc9572756 batman-adv: agglo... |
574 |
ret = recv_bat_ogm_packet(skb, hard_iface); |
c6c8fea29 net: Add batman-a... |
575 576 577 578 |
break; /* batman icmp packet */ case BAT_ICMP: |
e6c10f433 batman-adv: renam... |
579 |
ret = recv_icmp_packet(skb, hard_iface); |
c6c8fea29 net: Add batman-a... |
580 581 582 583 |
break; /* unicast packet */ case BAT_UNICAST: |
e6c10f433 batman-adv: renam... |
584 |
ret = recv_unicast_packet(skb, hard_iface); |
c6c8fea29 net: Add batman-a... |
585 586 587 588 |
break; /* fragmented unicast packet */ case BAT_UNICAST_FRAG: |
e6c10f433 batman-adv: renam... |
589 |
ret = recv_ucast_frag_packet(skb, hard_iface); |
c6c8fea29 net: Add batman-a... |
590 591 592 593 |
break; /* broadcast packet */ case BAT_BCAST: |
e6c10f433 batman-adv: renam... |
594 |
ret = recv_bcast_packet(skb, hard_iface); |
c6c8fea29 net: Add batman-a... |
595 596 597 598 |
break; /* vis packet */ case BAT_VIS: |
e6c10f433 batman-adv: renam... |
599 |
ret = recv_vis_packet(skb, hard_iface); |
c6c8fea29 net: Add batman-a... |
600 |
break; |
a73105b8d batman-adv: impro... |
601 602 603 604 |
/* Translation table query (request or response) */ case BAT_TT_QUERY: ret = recv_tt_query(skb, hard_iface); break; |
cc47f66e6 batman-adv: impro... |
605 606 607 608 |
/* Roaming advertisement */ case BAT_ROAM_ADV: ret = recv_roam_adv(skb, hard_iface); break; |
c6c8fea29 net: Add batman-a... |
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 |
default: ret = NET_RX_DROP; } if (ret == NET_RX_DROP) kfree_skb(skb); /* return NET_RX_SUCCESS in any case as we * most probably dropped the packet for * routing-logical reasons. */ return NET_RX_SUCCESS; err_free: kfree_skb(skb); err_out: return NET_RX_DROP; } |
bc2790808 batman-adv: detec... |
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
/* This function returns true if the interface represented by ifindex is a * 802.11 wireless device */ bool is_wifi_iface(int ifindex) { struct net_device *net_device = NULL; bool ret = false; if (ifindex == NULL_IFINDEX) goto out; net_device = dev_get_by_index(&init_net, ifindex); if (!net_device) goto out; #ifdef CONFIG_WIRELESS_EXT /* pre-cfg80211 drivers have to implement WEXT, so it is possible to * check for wireless_handlers != NULL */ if (net_device->wireless_handlers) ret = true; else #endif /* cfg80211 drivers have to set ieee80211_ptr */ if (net_device->ieee80211_ptr) ret = true; out: if (net_device) dev_put(net_device); return ret; } |
c6c8fea29 net: Add batman-a... |
656 657 658 |
struct notifier_block hard_if_notifier = { .notifier_call = hard_if_event, }; |