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