Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/batman-adv/soft-interface.c
15109 views
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 "soft-interface.h"
24
#include "hard-interface.h"
25
#include "routing.h"
26
#include "send.h"
27
#include "bat_debugfs.h"
28
#include "translation-table.h"
29
#include "hash.h"
30
#include "gateway_common.h"
31
#include "gateway_client.h"
32
#include "bat_sysfs.h"
33
#include <linux/slab.h>
34
#include <linux/ethtool.h>
35
#include <linux/etherdevice.h>
36
#include <linux/if_vlan.h>
37
#include "unicast.h"
38
39
40
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
41
static void bat_get_drvinfo(struct net_device *dev,
42
struct ethtool_drvinfo *info);
43
static u32 bat_get_msglevel(struct net_device *dev);
44
static void bat_set_msglevel(struct net_device *dev, u32 value);
45
static u32 bat_get_link(struct net_device *dev);
46
47
static const struct ethtool_ops bat_ethtool_ops = {
48
.get_settings = bat_get_settings,
49
.get_drvinfo = bat_get_drvinfo,
50
.get_msglevel = bat_get_msglevel,
51
.set_msglevel = bat_set_msglevel,
52
.get_link = bat_get_link,
53
};
54
55
int my_skb_head_push(struct sk_buff *skb, unsigned int len)
56
{
57
int result;
58
59
/**
60
* TODO: We must check if we can release all references to non-payload
61
* data using skb_header_release in our skbs to allow skb_cow_header to
62
* work optimally. This means that those skbs are not allowed to read
63
* or write any data which is before the current position of skb->data
64
* after that call and thus allow other skbs with the same data buffer
65
* to write freely in that area.
66
*/
67
result = skb_cow_head(skb, len);
68
if (result < 0)
69
return result;
70
71
skb_push(skb, len);
72
return 0;
73
}
74
75
static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
76
{
77
if (atomic_dec_and_test(&softif_neigh->refcount))
78
kfree_rcu(softif_neigh, rcu);
79
}
80
81
static void softif_neigh_vid_free_rcu(struct rcu_head *rcu)
82
{
83
struct softif_neigh_vid *softif_neigh_vid;
84
struct softif_neigh *softif_neigh;
85
struct hlist_node *node, *node_tmp;
86
struct bat_priv *bat_priv;
87
88
softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu);
89
bat_priv = softif_neigh_vid->bat_priv;
90
91
spin_lock_bh(&bat_priv->softif_neigh_lock);
92
hlist_for_each_entry_safe(softif_neigh, node, node_tmp,
93
&softif_neigh_vid->softif_neigh_list, list) {
94
hlist_del_rcu(&softif_neigh->list);
95
softif_neigh_free_ref(softif_neigh);
96
}
97
spin_unlock_bh(&bat_priv->softif_neigh_lock);
98
99
kfree(softif_neigh_vid);
100
}
101
102
static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid)
103
{
104
if (atomic_dec_and_test(&softif_neigh_vid->refcount))
105
call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu);
106
}
107
108
static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv,
109
short vid)
110
{
111
struct softif_neigh_vid *softif_neigh_vid;
112
struct hlist_node *node;
113
114
rcu_read_lock();
115
hlist_for_each_entry_rcu(softif_neigh_vid, node,
116
&bat_priv->softif_neigh_vids, list) {
117
if (softif_neigh_vid->vid != vid)
118
continue;
119
120
if (!atomic_inc_not_zero(&softif_neigh_vid->refcount))
121
continue;
122
123
goto out;
124
}
125
126
softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid),
127
GFP_ATOMIC);
128
if (!softif_neigh_vid)
129
goto out;
130
131
softif_neigh_vid->vid = vid;
132
softif_neigh_vid->bat_priv = bat_priv;
133
134
/* initialize with 2 - caller decrements counter by one */
135
atomic_set(&softif_neigh_vid->refcount, 2);
136
INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list);
137
INIT_HLIST_NODE(&softif_neigh_vid->list);
138
spin_lock_bh(&bat_priv->softif_neigh_vid_lock);
139
hlist_add_head_rcu(&softif_neigh_vid->list,
140
&bat_priv->softif_neigh_vids);
141
spin_unlock_bh(&bat_priv->softif_neigh_vid_lock);
142
143
out:
144
rcu_read_unlock();
145
return softif_neigh_vid;
146
}
147
148
static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
149
uint8_t *addr, short vid)
150
{
151
struct softif_neigh_vid *softif_neigh_vid;
152
struct softif_neigh *softif_neigh = NULL;
153
struct hlist_node *node;
154
155
softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid);
156
if (!softif_neigh_vid)
157
goto out;
158
159
rcu_read_lock();
160
hlist_for_each_entry_rcu(softif_neigh, node,
161
&softif_neigh_vid->softif_neigh_list,
162
list) {
163
if (!compare_eth(softif_neigh->addr, addr))
164
continue;
165
166
if (!atomic_inc_not_zero(&softif_neigh->refcount))
167
continue;
168
169
softif_neigh->last_seen = jiffies;
170
goto unlock;
171
}
172
173
softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
174
if (!softif_neigh)
175
goto unlock;
176
177
memcpy(softif_neigh->addr, addr, ETH_ALEN);
178
softif_neigh->last_seen = jiffies;
179
/* initialize with 2 - caller decrements counter by one */
180
atomic_set(&softif_neigh->refcount, 2);
181
182
INIT_HLIST_NODE(&softif_neigh->list);
183
spin_lock_bh(&bat_priv->softif_neigh_lock);
184
hlist_add_head_rcu(&softif_neigh->list,
185
&softif_neigh_vid->softif_neigh_list);
186
spin_unlock_bh(&bat_priv->softif_neigh_lock);
187
188
unlock:
189
rcu_read_unlock();
190
out:
191
if (softif_neigh_vid)
192
softif_neigh_vid_free_ref(softif_neigh_vid);
193
return softif_neigh;
194
}
195
196
static struct softif_neigh *softif_neigh_get_selected(
197
struct softif_neigh_vid *softif_neigh_vid)
198
{
199
struct softif_neigh *softif_neigh;
200
201
rcu_read_lock();
202
softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh);
203
204
if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount))
205
softif_neigh = NULL;
206
207
rcu_read_unlock();
208
return softif_neigh;
209
}
210
211
static struct softif_neigh *softif_neigh_vid_get_selected(
212
struct bat_priv *bat_priv,
213
short vid)
214
{
215
struct softif_neigh_vid *softif_neigh_vid;
216
struct softif_neigh *softif_neigh = NULL;
217
218
softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid);
219
if (!softif_neigh_vid)
220
goto out;
221
222
softif_neigh = softif_neigh_get_selected(softif_neigh_vid);
223
out:
224
if (softif_neigh_vid)
225
softif_neigh_vid_free_ref(softif_neigh_vid);
226
return softif_neigh;
227
}
228
229
static void softif_neigh_vid_select(struct bat_priv *bat_priv,
230
struct softif_neigh *new_neigh,
231
short vid)
232
{
233
struct softif_neigh_vid *softif_neigh_vid;
234
struct softif_neigh *curr_neigh;
235
236
softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid);
237
if (!softif_neigh_vid)
238
goto out;
239
240
spin_lock_bh(&bat_priv->softif_neigh_lock);
241
242
if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount))
243
new_neigh = NULL;
244
245
curr_neigh = softif_neigh_vid->softif_neigh;
246
rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh);
247
248
if ((curr_neigh) && (!new_neigh))
249
bat_dbg(DBG_ROUTES, bat_priv,
250
"Removing mesh exit point on vid: %d (prev: %pM).\n",
251
vid, curr_neigh->addr);
252
else if ((curr_neigh) && (new_neigh))
253
bat_dbg(DBG_ROUTES, bat_priv,
254
"Changing mesh exit point on vid: %d from %pM "
255
"to %pM.\n", vid, curr_neigh->addr, new_neigh->addr);
256
else if ((!curr_neigh) && (new_neigh))
257
bat_dbg(DBG_ROUTES, bat_priv,
258
"Setting mesh exit point on vid: %d to %pM.\n",
259
vid, new_neigh->addr);
260
261
if (curr_neigh)
262
softif_neigh_free_ref(curr_neigh);
263
264
spin_unlock_bh(&bat_priv->softif_neigh_lock);
265
266
out:
267
if (softif_neigh_vid)
268
softif_neigh_vid_free_ref(softif_neigh_vid);
269
}
270
271
static void softif_neigh_vid_deselect(struct bat_priv *bat_priv,
272
struct softif_neigh_vid *softif_neigh_vid)
273
{
274
struct softif_neigh *curr_neigh;
275
struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp;
276
struct hard_iface *primary_if = NULL;
277
struct hlist_node *node;
278
279
primary_if = primary_if_get_selected(bat_priv);
280
if (!primary_if)
281
goto out;
282
283
/* find new softif_neigh immediately to avoid temporary loops */
284
rcu_read_lock();
285
curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh);
286
287
hlist_for_each_entry_rcu(softif_neigh_tmp, node,
288
&softif_neigh_vid->softif_neigh_list,
289
list) {
290
if (softif_neigh_tmp == curr_neigh)
291
continue;
292
293
/* we got a neighbor but its mac is 'bigger' than ours */
294
if (memcmp(primary_if->net_dev->dev_addr,
295
softif_neigh_tmp->addr, ETH_ALEN) < 0)
296
continue;
297
298
if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount))
299
continue;
300
301
softif_neigh = softif_neigh_tmp;
302
goto unlock;
303
}
304
305
unlock:
306
rcu_read_unlock();
307
out:
308
softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid);
309
310
if (primary_if)
311
hardif_free_ref(primary_if);
312
if (softif_neigh)
313
softif_neigh_free_ref(softif_neigh);
314
}
315
316
int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
317
{
318
struct net_device *net_dev = (struct net_device *)seq->private;
319
struct bat_priv *bat_priv = netdev_priv(net_dev);
320
struct softif_neigh_vid *softif_neigh_vid;
321
struct softif_neigh *softif_neigh;
322
struct hard_iface *primary_if;
323
struct hlist_node *node, *node_tmp;
324
struct softif_neigh *curr_softif_neigh;
325
int ret = 0, last_seen_secs, last_seen_msecs;
326
327
primary_if = primary_if_get_selected(bat_priv);
328
if (!primary_if) {
329
ret = seq_printf(seq, "BATMAN mesh %s disabled - "
330
"please specify interfaces to enable it\n",
331
net_dev->name);
332
goto out;
333
}
334
335
if (primary_if->if_status != IF_ACTIVE) {
336
ret = seq_printf(seq, "BATMAN mesh %s "
337
"disabled - primary interface not active\n",
338
net_dev->name);
339
goto out;
340
}
341
342
seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
343
344
rcu_read_lock();
345
hlist_for_each_entry_rcu(softif_neigh_vid, node,
346
&bat_priv->softif_neigh_vids, list) {
347
seq_printf(seq, " %-15s %s on vid: %d\n",
348
"Originator", "last-seen", softif_neigh_vid->vid);
349
350
curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid);
351
352
hlist_for_each_entry_rcu(softif_neigh, node_tmp,
353
&softif_neigh_vid->softif_neigh_list,
354
list) {
355
last_seen_secs = jiffies_to_msecs(jiffies -
356
softif_neigh->last_seen) / 1000;
357
last_seen_msecs = jiffies_to_msecs(jiffies -
358
softif_neigh->last_seen) % 1000;
359
seq_printf(seq, "%s %pM %3i.%03is\n",
360
curr_softif_neigh == softif_neigh
361
? "=>" : " ", softif_neigh->addr,
362
last_seen_secs, last_seen_msecs);
363
}
364
365
if (curr_softif_neigh)
366
softif_neigh_free_ref(curr_softif_neigh);
367
368
seq_printf(seq, "\n");
369
}
370
rcu_read_unlock();
371
372
out:
373
if (primary_if)
374
hardif_free_ref(primary_if);
375
return ret;
376
}
377
378
void softif_neigh_purge(struct bat_priv *bat_priv)
379
{
380
struct softif_neigh *softif_neigh, *curr_softif_neigh;
381
struct softif_neigh_vid *softif_neigh_vid;
382
struct hlist_node *node, *node_tmp, *node_tmp2;
383
char do_deselect;
384
385
rcu_read_lock();
386
hlist_for_each_entry_rcu(softif_neigh_vid, node,
387
&bat_priv->softif_neigh_vids, list) {
388
if (!atomic_inc_not_zero(&softif_neigh_vid->refcount))
389
continue;
390
391
curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid);
392
do_deselect = 0;
393
394
spin_lock_bh(&bat_priv->softif_neigh_lock);
395
hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2,
396
&softif_neigh_vid->softif_neigh_list,
397
list) {
398
if ((!time_after(jiffies, softif_neigh->last_seen +
399
msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) &&
400
(atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
401
continue;
402
403
if (curr_softif_neigh == softif_neigh) {
404
bat_dbg(DBG_ROUTES, bat_priv,
405
"Current mesh exit point on vid: %d "
406
"'%pM' vanished.\n",
407
softif_neigh_vid->vid,
408
softif_neigh->addr);
409
do_deselect = 1;
410
}
411
412
hlist_del_rcu(&softif_neigh->list);
413
softif_neigh_free_ref(softif_neigh);
414
}
415
spin_unlock_bh(&bat_priv->softif_neigh_lock);
416
417
/* soft_neigh_vid_deselect() needs to acquire the
418
* softif_neigh_lock */
419
if (do_deselect)
420
softif_neigh_vid_deselect(bat_priv, softif_neigh_vid);
421
422
if (curr_softif_neigh)
423
softif_neigh_free_ref(curr_softif_neigh);
424
425
softif_neigh_vid_free_ref(softif_neigh_vid);
426
}
427
rcu_read_unlock();
428
429
spin_lock_bh(&bat_priv->softif_neigh_vid_lock);
430
hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp,
431
&bat_priv->softif_neigh_vids, list) {
432
if (!hlist_empty(&softif_neigh_vid->softif_neigh_list))
433
continue;
434
435
hlist_del_rcu(&softif_neigh_vid->list);
436
softif_neigh_vid_free_ref(softif_neigh_vid);
437
}
438
spin_unlock_bh(&bat_priv->softif_neigh_vid_lock);
439
440
}
441
442
static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
443
short vid)
444
{
445
struct bat_priv *bat_priv = netdev_priv(dev);
446
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
447
struct batman_packet *batman_packet;
448
struct softif_neigh *softif_neigh = NULL;
449
struct hard_iface *primary_if = NULL;
450
struct softif_neigh *curr_softif_neigh = NULL;
451
452
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
453
batman_packet = (struct batman_packet *)
454
(skb->data + ETH_HLEN + VLAN_HLEN);
455
else
456
batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
457
458
if (batman_packet->version != COMPAT_VERSION)
459
goto out;
460
461
if (batman_packet->packet_type != BAT_PACKET)
462
goto out;
463
464
if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
465
goto out;
466
467
if (is_my_mac(batman_packet->orig))
468
goto out;
469
470
softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
471
if (!softif_neigh)
472
goto out;
473
474
curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid);
475
if (curr_softif_neigh == softif_neigh)
476
goto out;
477
478
primary_if = primary_if_get_selected(bat_priv);
479
if (!primary_if)
480
goto out;
481
482
/* we got a neighbor but its mac is 'bigger' than ours */
483
if (memcmp(primary_if->net_dev->dev_addr,
484
softif_neigh->addr, ETH_ALEN) < 0)
485
goto out;
486
487
/* close own batX device and use softif_neigh as exit node */
488
if (!curr_softif_neigh) {
489
softif_neigh_vid_select(bat_priv, softif_neigh, vid);
490
goto out;
491
}
492
493
/* switch to new 'smallest neighbor' */
494
if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0)
495
softif_neigh_vid_select(bat_priv, softif_neigh, vid);
496
497
out:
498
kfree_skb(skb);
499
if (softif_neigh)
500
softif_neigh_free_ref(softif_neigh);
501
if (curr_softif_neigh)
502
softif_neigh_free_ref(curr_softif_neigh);
503
if (primary_if)
504
hardif_free_ref(primary_if);
505
return;
506
}
507
508
static int interface_open(struct net_device *dev)
509
{
510
netif_start_queue(dev);
511
return 0;
512
}
513
514
static int interface_release(struct net_device *dev)
515
{
516
netif_stop_queue(dev);
517
return 0;
518
}
519
520
static struct net_device_stats *interface_stats(struct net_device *dev)
521
{
522
struct bat_priv *bat_priv = netdev_priv(dev);
523
return &bat_priv->stats;
524
}
525
526
static int interface_set_mac_addr(struct net_device *dev, void *p)
527
{
528
struct bat_priv *bat_priv = netdev_priv(dev);
529
struct sockaddr *addr = p;
530
531
if (!is_valid_ether_addr(addr->sa_data))
532
return -EADDRNOTAVAIL;
533
534
/* only modify transtable if it has been initialised before */
535
if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
536
tt_local_remove(bat_priv, dev->dev_addr,
537
"mac address changed");
538
tt_local_add(dev, addr->sa_data);
539
}
540
541
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
542
return 0;
543
}
544
545
static int interface_change_mtu(struct net_device *dev, int new_mtu)
546
{
547
/* check ranges */
548
if ((new_mtu < 68) || (new_mtu > hardif_min_mtu(dev)))
549
return -EINVAL;
550
551
dev->mtu = new_mtu;
552
553
return 0;
554
}
555
556
int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
557
{
558
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
559
struct bat_priv *bat_priv = netdev_priv(soft_iface);
560
struct hard_iface *primary_if = NULL;
561
struct bcast_packet *bcast_packet;
562
struct vlan_ethhdr *vhdr;
563
struct softif_neigh *curr_softif_neigh = NULL;
564
int data_len = skb->len, ret;
565
short vid = -1;
566
bool do_bcast = false;
567
568
if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
569
goto dropped;
570
571
soft_iface->trans_start = jiffies;
572
573
switch (ntohs(ethhdr->h_proto)) {
574
case ETH_P_8021Q:
575
vhdr = (struct vlan_ethhdr *)skb->data;
576
vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
577
578
if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
579
break;
580
581
/* fall through */
582
case ETH_P_BATMAN:
583
softif_batman_recv(skb, soft_iface, vid);
584
goto end;
585
}
586
587
/**
588
* if we have a another chosen mesh exit node in range
589
* it will transport the packets to the mesh
590
*/
591
curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid);
592
if (curr_softif_neigh)
593
goto dropped;
594
595
/* TODO: check this for locks */
596
tt_local_add(soft_iface, ethhdr->h_source);
597
598
if (is_multicast_ether_addr(ethhdr->h_dest)) {
599
ret = gw_is_target(bat_priv, skb);
600
601
if (ret < 0)
602
goto dropped;
603
604
if (ret == 0)
605
do_bcast = true;
606
}
607
608
/* ethernet packet should be broadcasted */
609
if (do_bcast) {
610
primary_if = primary_if_get_selected(bat_priv);
611
if (!primary_if)
612
goto dropped;
613
614
if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
615
goto dropped;
616
617
bcast_packet = (struct bcast_packet *)skb->data;
618
bcast_packet->version = COMPAT_VERSION;
619
bcast_packet->ttl = TTL;
620
621
/* batman packet type: broadcast */
622
bcast_packet->packet_type = BAT_BCAST;
623
624
/* hw address of first interface is the orig mac because only
625
* this mac is known throughout the mesh */
626
memcpy(bcast_packet->orig,
627
primary_if->net_dev->dev_addr, ETH_ALEN);
628
629
/* set broadcast sequence number */
630
bcast_packet->seqno =
631
htonl(atomic_inc_return(&bat_priv->bcast_seqno));
632
633
add_bcast_packet_to_list(bat_priv, skb);
634
635
/* a copy is stored in the bcast list, therefore removing
636
* the original skb. */
637
kfree_skb(skb);
638
639
/* unicast packet */
640
} else {
641
ret = unicast_send_skb(skb, bat_priv);
642
if (ret != 0)
643
goto dropped_freed;
644
}
645
646
bat_priv->stats.tx_packets++;
647
bat_priv->stats.tx_bytes += data_len;
648
goto end;
649
650
dropped:
651
kfree_skb(skb);
652
dropped_freed:
653
bat_priv->stats.tx_dropped++;
654
end:
655
if (curr_softif_neigh)
656
softif_neigh_free_ref(curr_softif_neigh);
657
if (primary_if)
658
hardif_free_ref(primary_if);
659
return NETDEV_TX_OK;
660
}
661
662
void interface_rx(struct net_device *soft_iface,
663
struct sk_buff *skb, struct hard_iface *recv_if,
664
int hdr_size)
665
{
666
struct bat_priv *bat_priv = netdev_priv(soft_iface);
667
struct unicast_packet *unicast_packet;
668
struct ethhdr *ethhdr;
669
struct vlan_ethhdr *vhdr;
670
struct softif_neigh *curr_softif_neigh = NULL;
671
short vid = -1;
672
int ret;
673
674
/* check if enough space is available for pulling, and pull */
675
if (!pskb_may_pull(skb, hdr_size))
676
goto dropped;
677
678
skb_pull_rcsum(skb, hdr_size);
679
skb_reset_mac_header(skb);
680
681
ethhdr = (struct ethhdr *)skb_mac_header(skb);
682
683
switch (ntohs(ethhdr->h_proto)) {
684
case ETH_P_8021Q:
685
vhdr = (struct vlan_ethhdr *)skb->data;
686
vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
687
688
if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
689
break;
690
691
/* fall through */
692
case ETH_P_BATMAN:
693
goto dropped;
694
}
695
696
/**
697
* if we have a another chosen mesh exit node in range
698
* it will transport the packets to the non-mesh network
699
*/
700
curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid);
701
if (curr_softif_neigh) {
702
skb_push(skb, hdr_size);
703
unicast_packet = (struct unicast_packet *)skb->data;
704
705
if ((unicast_packet->packet_type != BAT_UNICAST) &&
706
(unicast_packet->packet_type != BAT_UNICAST_FRAG))
707
goto dropped;
708
709
skb_reset_mac_header(skb);
710
711
memcpy(unicast_packet->dest,
712
curr_softif_neigh->addr, ETH_ALEN);
713
ret = route_unicast_packet(skb, recv_if);
714
if (ret == NET_RX_DROP)
715
goto dropped;
716
717
goto out;
718
}
719
720
/* skb->dev & skb->pkt_type are set here */
721
if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
722
goto dropped;
723
skb->protocol = eth_type_trans(skb, soft_iface);
724
725
/* should not be necessary anymore as we use skb_pull_rcsum()
726
* TODO: please verify this and remove this TODO
727
* -- Dec 21st 2009, Simon Wunderlich */
728
729
/* skb->ip_summed = CHECKSUM_UNNECESSARY;*/
730
731
bat_priv->stats.rx_packets++;
732
bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
733
734
soft_iface->last_rx = jiffies;
735
736
netif_rx(skb);
737
goto out;
738
739
dropped:
740
kfree_skb(skb);
741
out:
742
if (curr_softif_neigh)
743
softif_neigh_free_ref(curr_softif_neigh);
744
return;
745
}
746
747
#ifdef HAVE_NET_DEVICE_OPS
748
static const struct net_device_ops bat_netdev_ops = {
749
.ndo_open = interface_open,
750
.ndo_stop = interface_release,
751
.ndo_get_stats = interface_stats,
752
.ndo_set_mac_address = interface_set_mac_addr,
753
.ndo_change_mtu = interface_change_mtu,
754
.ndo_start_xmit = interface_tx,
755
.ndo_validate_addr = eth_validate_addr
756
};
757
#endif
758
759
static void interface_setup(struct net_device *dev)
760
{
761
struct bat_priv *priv = netdev_priv(dev);
762
char dev_addr[ETH_ALEN];
763
764
ether_setup(dev);
765
766
#ifdef HAVE_NET_DEVICE_OPS
767
dev->netdev_ops = &bat_netdev_ops;
768
#else
769
dev->open = interface_open;
770
dev->stop = interface_release;
771
dev->get_stats = interface_stats;
772
dev->set_mac_address = interface_set_mac_addr;
773
dev->change_mtu = interface_change_mtu;
774
dev->hard_start_xmit = interface_tx;
775
#endif
776
dev->destructor = free_netdev;
777
dev->tx_queue_len = 0;
778
779
/**
780
* can't call min_mtu, because the needed variables
781
* have not been initialized yet
782
*/
783
dev->mtu = ETH_DATA_LEN;
784
/* reserve more space in the skbuff for our header */
785
dev->hard_header_len = BAT_HEADER_LEN;
786
787
/* generate random address */
788
random_ether_addr(dev_addr);
789
memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
790
791
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
792
793
memset(priv, 0, sizeof(struct bat_priv));
794
}
795
796
struct net_device *softif_create(char *name)
797
{
798
struct net_device *soft_iface;
799
struct bat_priv *bat_priv;
800
int ret;
801
802
soft_iface = alloc_netdev(sizeof(struct bat_priv) , name,
803
interface_setup);
804
805
if (!soft_iface) {
806
pr_err("Unable to allocate the batman interface: %s\n", name);
807
goto out;
808
}
809
810
ret = register_netdevice(soft_iface);
811
if (ret < 0) {
812
pr_err("Unable to register the batman interface '%s': %i\n",
813
name, ret);
814
goto free_soft_iface;
815
}
816
817
bat_priv = netdev_priv(soft_iface);
818
819
atomic_set(&bat_priv->aggregated_ogms, 1);
820
atomic_set(&bat_priv->bonding, 0);
821
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
822
atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
823
atomic_set(&bat_priv->gw_sel_class, 20);
824
atomic_set(&bat_priv->gw_bandwidth, 41);
825
atomic_set(&bat_priv->orig_interval, 1000);
826
atomic_set(&bat_priv->hop_penalty, 10);
827
atomic_set(&bat_priv->log_level, 0);
828
atomic_set(&bat_priv->fragmentation, 1);
829
atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
830
atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
831
832
atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
833
atomic_set(&bat_priv->bcast_seqno, 1);
834
atomic_set(&bat_priv->tt_local_changed, 0);
835
836
bat_priv->primary_if = NULL;
837
bat_priv->num_ifaces = 0;
838
839
ret = sysfs_add_meshif(soft_iface);
840
if (ret < 0)
841
goto unreg_soft_iface;
842
843
ret = debugfs_add_meshif(soft_iface);
844
if (ret < 0)
845
goto unreg_sysfs;
846
847
ret = mesh_init(soft_iface);
848
if (ret < 0)
849
goto unreg_debugfs;
850
851
return soft_iface;
852
853
unreg_debugfs:
854
debugfs_del_meshif(soft_iface);
855
unreg_sysfs:
856
sysfs_del_meshif(soft_iface);
857
unreg_soft_iface:
858
unregister_netdev(soft_iface);
859
return NULL;
860
861
free_soft_iface:
862
free_netdev(soft_iface);
863
out:
864
return NULL;
865
}
866
867
void softif_destroy(struct net_device *soft_iface)
868
{
869
debugfs_del_meshif(soft_iface);
870
sysfs_del_meshif(soft_iface);
871
mesh_free(soft_iface);
872
unregister_netdevice(soft_iface);
873
}
874
875
int softif_is_valid(struct net_device *net_dev)
876
{
877
#ifdef HAVE_NET_DEVICE_OPS
878
if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
879
return 1;
880
#else
881
if (net_dev->hard_start_xmit == interface_tx)
882
return 1;
883
#endif
884
885
return 0;
886
}
887
888
/* ethtool */
889
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
890
{
891
cmd->supported = 0;
892
cmd->advertising = 0;
893
ethtool_cmd_speed_set(cmd, SPEED_10);
894
cmd->duplex = DUPLEX_FULL;
895
cmd->port = PORT_TP;
896
cmd->phy_address = 0;
897
cmd->transceiver = XCVR_INTERNAL;
898
cmd->autoneg = AUTONEG_DISABLE;
899
cmd->maxtxpkt = 0;
900
cmd->maxrxpkt = 0;
901
902
return 0;
903
}
904
905
static void bat_get_drvinfo(struct net_device *dev,
906
struct ethtool_drvinfo *info)
907
{
908
strcpy(info->driver, "B.A.T.M.A.N. advanced");
909
strcpy(info->version, SOURCE_VERSION);
910
strcpy(info->fw_version, "N/A");
911
strcpy(info->bus_info, "batman");
912
}
913
914
static u32 bat_get_msglevel(struct net_device *dev)
915
{
916
return -EOPNOTSUPP;
917
}
918
919
static void bat_set_msglevel(struct net_device *dev, u32 value)
920
{
921
}
922
923
static u32 bat_get_link(struct net_device *dev)
924
{
925
return 1;
926
}
927
928
929