~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/batman-adv/soft-interface.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
 
2
 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
3
3
 *
4
4
 * Marek Lindner, Simon Wunderlich
5
5
 *
26
26
#include "send.h"
27
27
#include "bat_debugfs.h"
28
28
#include "translation-table.h"
29
 
#include "types.h"
30
29
#include "hash.h"
31
30
#include "gateway_common.h"
32
31
#include "gateway_client.h"
33
 
#include "send.h"
34
32
#include "bat_sysfs.h"
35
33
#include <linux/slab.h>
36
34
#include <linux/ethtool.h>
37
35
#include <linux/etherdevice.h>
38
36
#include <linux/if_vlan.h>
39
37
#include "unicast.h"
40
 
#include "routing.h"
41
38
 
42
39
 
43
40
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
46
43
static u32 bat_get_msglevel(struct net_device *dev);
47
44
static void bat_set_msglevel(struct net_device *dev, u32 value);
48
45
static u32 bat_get_link(struct net_device *dev);
49
 
static u32 bat_get_rx_csum(struct net_device *dev);
50
 
static int bat_set_rx_csum(struct net_device *dev, u32 data);
51
46
 
52
47
static const struct ethtool_ops bat_ethtool_ops = {
53
48
        .get_settings = bat_get_settings,
55
50
        .get_msglevel = bat_get_msglevel,
56
51
        .set_msglevel = bat_set_msglevel,
57
52
        .get_link = bat_get_link,
58
 
        .get_rx_csum = bat_get_rx_csum,
59
 
        .set_rx_csum = bat_set_rx_csum
60
53
};
61
54
 
62
55
int my_skb_head_push(struct sk_buff *skb, unsigned int len)
79
72
        return 0;
80
73
}
81
74
 
82
 
static void softif_neigh_free_ref(struct kref *refcount)
83
 
{
84
 
        struct softif_neigh *softif_neigh;
85
 
 
86
 
        softif_neigh = container_of(refcount, struct softif_neigh, refcount);
87
 
        kfree(softif_neigh);
88
 
}
89
 
 
90
 
static void softif_neigh_free_rcu(struct rcu_head *rcu)
91
 
{
92
 
        struct softif_neigh *softif_neigh;
93
 
 
94
 
        softif_neigh = container_of(rcu, struct softif_neigh, rcu);
95
 
        kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
96
 
}
97
 
 
98
 
void softif_neigh_purge(struct bat_priv *bat_priv)
99
 
{
100
 
        struct softif_neigh *softif_neigh, *softif_neigh_tmp;
 
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;
101
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;
102
90
 
103
91
        spin_lock_bh(&bat_priv->softif_neigh_lock);
104
 
 
105
92
        hlist_for_each_entry_safe(softif_neigh, node, node_tmp,
106
 
                                  &bat_priv->softif_neigh_list, list) {
107
 
 
108
 
                if ((!time_after(jiffies, softif_neigh->last_seen +
109
 
                                msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) &&
110
 
                    (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
111
 
                        continue;
112
 
 
 
93
                                  &softif_neigh_vid->softif_neigh_list, list) {
113
94
                hlist_del_rcu(&softif_neigh->list);
114
 
 
115
 
                if (bat_priv->softif_neigh == softif_neigh) {
116
 
                        bat_dbg(DBG_ROUTES, bat_priv,
117
 
                                 "Current mesh exit point '%pM' vanished "
118
 
                                 "(vid: %d).\n",
119
 
                                 softif_neigh->addr, softif_neigh->vid);
120
 
                        softif_neigh_tmp = bat_priv->softif_neigh;
121
 
                        bat_priv->softif_neigh = NULL;
122
 
                        kref_put(&softif_neigh_tmp->refcount,
123
 
                                 softif_neigh_free_ref);
124
 
                }
125
 
 
126
 
                call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
 
95
                softif_neigh_free_ref(softif_neigh);
127
96
        }
128
 
 
129
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;
130
146
}
131
147
 
132
148
static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
133
149
                                             uint8_t *addr, short vid)
134
150
{
135
 
        struct softif_neigh *softif_neigh;
 
151
        struct softif_neigh_vid *softif_neigh_vid;
 
152
        struct softif_neigh *softif_neigh = NULL;
136
153
        struct hlist_node *node;
137
154
 
 
155
        softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid);
 
156
        if (!softif_neigh_vid)
 
157
                goto out;
 
158
 
138
159
        rcu_read_lock();
139
160
        hlist_for_each_entry_rcu(softif_neigh, node,
140
 
                                 &bat_priv->softif_neigh_list, list) {
141
 
                if (memcmp(softif_neigh->addr, addr, ETH_ALEN) != 0)
 
161
                                 &softif_neigh_vid->softif_neigh_list,
 
162
                                 list) {
 
163
                if (!compare_eth(softif_neigh->addr, addr))
142
164
                        continue;
143
165
 
144
 
                if (softif_neigh->vid != vid)
 
166
                if (!atomic_inc_not_zero(&softif_neigh->refcount))
145
167
                        continue;
146
168
 
147
169
                softif_neigh->last_seen = jiffies;
148
 
                goto found;
 
170
                goto unlock;
149
171
        }
150
172
 
151
173
        softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
152
174
        if (!softif_neigh)
153
 
                goto out;
 
175
                goto unlock;
154
176
 
155
177
        memcpy(softif_neigh->addr, addr, ETH_ALEN);
156
 
        softif_neigh->vid = vid;
157
178
        softif_neigh->last_seen = jiffies;
158
 
        kref_init(&softif_neigh->refcount);
 
179
        /* initialize with 2 - caller decrements counter by one */
 
180
        atomic_set(&softif_neigh->refcount, 2);
159
181
 
160
182
        INIT_HLIST_NODE(&softif_neigh->list);
161
183
        spin_lock_bh(&bat_priv->softif_neigh_lock);
162
 
        hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
163
 
        spin_unlock_bh(&bat_priv->softif_neigh_lock);
164
 
 
165
 
found:
166
 
        kref_get(&softif_neigh->refcount);
167
 
out:
168
 
        rcu_read_unlock();
169
 
        return softif_neigh;
 
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);
170
314
}
171
315
 
172
316
int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
173
317
{
174
318
        struct net_device *net_dev = (struct net_device *)seq->private;
175
319
        struct bat_priv *bat_priv = netdev_priv(net_dev);
 
320
        struct softif_neigh_vid *softif_neigh_vid;
176
321
        struct softif_neigh *softif_neigh;
177
 
        struct hlist_node *node;
178
 
        size_t buf_size, pos;
179
 
        char *buff;
180
 
 
181
 
        if (!bat_priv->primary_if) {
182
 
                return seq_printf(seq, "BATMAN mesh %s disabled - "
183
 
                               "please specify interfaces to enable it\n",
184
 
                               net_dev->name);
 
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;
185
340
        }
186
341
 
187
342
        seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
188
343
 
189
 
        buf_size = 1;
190
 
        /* Estimate length for: "   xx:xx:xx:xx:xx:xx\n" */
191
 
        rcu_read_lock();
192
 
        hlist_for_each_entry_rcu(softif_neigh, node,
193
 
                                 &bat_priv->softif_neigh_list, list)
194
 
                buf_size += 30;
195
 
        rcu_read_unlock();
196
 
 
197
 
        buff = kmalloc(buf_size, GFP_ATOMIC);
198
 
        if (!buff)
199
 
                return -ENOMEM;
200
 
 
201
 
        buff[0] = '\0';
202
 
        pos = 0;
203
 
 
204
 
        rcu_read_lock();
205
 
        hlist_for_each_entry_rcu(softif_neigh, node,
206
 
                                 &bat_priv->softif_neigh_list, list) {
207
 
                pos += snprintf(buff + pos, 31, "%s %pM (vid: %d)\n",
208
 
                                bat_priv->softif_neigh == softif_neigh
209
 
                                ? "=>" : "  ", softif_neigh->addr,
210
 
                                softif_neigh->vid);
211
 
        }
212
 
        rcu_read_unlock();
213
 
 
214
 
        seq_printf(seq, "%s", buff);
215
 
        kfree(buff);
216
 
        return 0;
 
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
 
217
440
}
218
441
 
219
442
static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
222
445
        struct bat_priv *bat_priv = netdev_priv(dev);
223
446
        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
224
447
        struct batman_packet *batman_packet;
225
 
        struct softif_neigh *softif_neigh, *softif_neigh_tmp;
 
448
        struct softif_neigh *softif_neigh = NULL;
 
449
        struct hard_iface *primary_if = NULL;
 
450
        struct softif_neigh *curr_softif_neigh = NULL;
226
451
 
227
452
        if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
228
453
                batman_packet = (struct batman_packet *)
231
456
                batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
232
457
 
233
458
        if (batman_packet->version != COMPAT_VERSION)
234
 
                goto err;
 
459
                goto out;
235
460
 
236
461
        if (batman_packet->packet_type != BAT_PACKET)
237
 
                goto err;
 
462
                goto out;
238
463
 
239
464
        if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
240
 
                goto err;
 
465
                goto out;
241
466
 
242
467
        if (is_my_mac(batman_packet->orig))
243
 
                goto err;
 
468
                goto out;
244
469
 
245
470
        softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
246
 
 
247
471
        if (!softif_neigh)
248
 
                goto err;
249
 
 
250
 
        if (bat_priv->softif_neigh == 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)
251
480
                goto out;
252
481
 
253
482
        /* we got a neighbor but its mac is 'bigger' than ours  */
254
 
        if (memcmp(bat_priv->primary_if->net_dev->dev_addr,
 
483
        if (memcmp(primary_if->net_dev->dev_addr,
255
484
                   softif_neigh->addr, ETH_ALEN) < 0)
256
485
                goto out;
257
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
 
258
493
        /* switch to new 'smallest neighbor' */
259
 
        if ((bat_priv->softif_neigh) &&
260
 
            (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr,
261
 
                                                        ETH_ALEN) < 0)) {
262
 
                bat_dbg(DBG_ROUTES, bat_priv,
263
 
                        "Changing mesh exit point from %pM (vid: %d) "
264
 
                        "to %pM (vid: %d).\n",
265
 
                         bat_priv->softif_neigh->addr,
266
 
                         bat_priv->softif_neigh->vid,
267
 
                         softif_neigh->addr, softif_neigh->vid);
268
 
                softif_neigh_tmp = bat_priv->softif_neigh;
269
 
                bat_priv->softif_neigh = softif_neigh;
270
 
                kref_put(&softif_neigh_tmp->refcount, softif_neigh_free_ref);
271
 
                /* we need to hold the additional reference */
272
 
                goto err;
273
 
        }
274
 
 
275
 
        /* close own batX device and use softif_neigh as exit node */
276
 
        if ((!bat_priv->softif_neigh) &&
277
 
            (memcmp(softif_neigh->addr,
278
 
                    bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
279
 
                bat_dbg(DBG_ROUTES, bat_priv,
280
 
                        "Setting mesh exit point to %pM (vid: %d).\n",
281
 
                        softif_neigh->addr, softif_neigh->vid);
282
 
                bat_priv->softif_neigh = softif_neigh;
283
 
                /* we need to hold the additional reference */
284
 
                goto err;
285
 
        }
 
494
        if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0)
 
495
                softif_neigh_vid_select(bat_priv, softif_neigh, vid);
286
496
 
287
497
out:
288
 
        kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
289
 
err:
290
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);
291
505
        return;
292
506
}
293
507
 
317
531
        if (!is_valid_ether_addr(addr->sa_data))
318
532
                return -EADDRNOTAVAIL;
319
533
 
320
 
        /* only modify hna-table if it has been initialised before */
 
534
        /* only modify transtable if it has been initialised before */
321
535
        if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
322
 
                hna_local_remove(bat_priv, dev->dev_addr,
 
536
                tt_local_remove(bat_priv, dev->dev_addr,
323
537
                                 "mac address changed");
324
 
                hna_local_add(dev, addr->sa_data);
 
538
                tt_local_add(dev, addr->sa_data);
325
539
        }
326
540
 
327
541
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
343
557
{
344
558
        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
345
559
        struct bat_priv *bat_priv = netdev_priv(soft_iface);
 
560
        struct hard_iface *primary_if = NULL;
346
561
        struct bcast_packet *bcast_packet;
347
562
        struct vlan_ethhdr *vhdr;
 
563
        struct softif_neigh *curr_softif_neigh = NULL;
348
564
        int data_len = skb->len, ret;
349
565
        short vid = -1;
350
566
        bool do_bcast = false;
372
588
         * if we have a another chosen mesh exit node in range
373
589
         * it will transport the packets to the mesh
374
590
         */
375
 
        if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid))
 
591
        curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid);
 
592
        if (curr_softif_neigh)
376
593
                goto dropped;
377
594
 
378
595
        /* TODO: check this for locks */
379
 
        hna_local_add(soft_iface, ethhdr->h_source);
 
596
        tt_local_add(soft_iface, ethhdr->h_source);
380
597
 
381
598
        if (is_multicast_ether_addr(ethhdr->h_dest)) {
382
599
                ret = gw_is_target(bat_priv, skb);
390
607
 
391
608
        /* ethernet packet should be broadcasted */
392
609
        if (do_bcast) {
393
 
                if (!bat_priv->primary_if)
 
610
                primary_if = primary_if_get_selected(bat_priv);
 
611
                if (!primary_if)
394
612
                        goto dropped;
395
613
 
396
614
                if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
406
624
                /* hw address of first interface is the orig mac because only
407
625
                 * this mac is known throughout the mesh */
408
626
                memcpy(bcast_packet->orig,
409
 
                       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
 
627
                       primary_if->net_dev->dev_addr, ETH_ALEN);
410
628
 
411
629
                /* set broadcast sequence number */
412
630
                bcast_packet->seqno =
434
652
dropped_freed:
435
653
        bat_priv->stats.tx_dropped++;
436
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);
437
659
        return NETDEV_TX_OK;
438
660
}
439
661
 
440
662
void interface_rx(struct net_device *soft_iface,
441
 
                  struct sk_buff *skb, struct batman_if *recv_if,
 
663
                  struct sk_buff *skb, struct hard_iface *recv_if,
442
664
                  int hdr_size)
443
665
{
444
666
        struct bat_priv *bat_priv = netdev_priv(soft_iface);
445
667
        struct unicast_packet *unicast_packet;
446
668
        struct ethhdr *ethhdr;
447
669
        struct vlan_ethhdr *vhdr;
 
670
        struct softif_neigh *curr_softif_neigh = NULL;
448
671
        short vid = -1;
449
672
        int ret;
450
673
 
474
697
         * if we have a another chosen mesh exit node in range
475
698
         * it will transport the packets to the non-mesh network
476
699
         */
477
 
        if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) {
 
700
        curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid);
 
701
        if (curr_softif_neigh) {
478
702
                skb_push(skb, hdr_size);
479
703
                unicast_packet = (struct unicast_packet *)skb->data;
480
704
 
485
709
                skb_reset_mac_header(skb);
486
710
 
487
711
                memcpy(unicast_packet->dest,
488
 
                       bat_priv->softif_neigh->addr, ETH_ALEN);
489
 
                ret = route_unicast_packet(skb, recv_if, hdr_size);
 
712
                       curr_softif_neigh->addr, ETH_ALEN);
 
713
                ret = route_unicast_packet(skb, recv_if);
490
714
                if (ret == NET_RX_DROP)
491
715
                        goto dropped;
492
716
 
498
722
                goto dropped;
499
723
        skb->protocol = eth_type_trans(skb, soft_iface);
500
724
 
501
 
        /* should not be neccesary anymore as we use skb_pull_rcsum()
 
725
        /* should not be necessary anymore as we use skb_pull_rcsum()
502
726
         * TODO: please verify this and remove this TODO
503
727
         * -- Dec 21st 2009, Simon Wunderlich */
504
728
 
510
734
        soft_iface->last_rx = jiffies;
511
735
 
512
736
        netif_rx(skb);
513
 
        return;
 
737
        goto out;
514
738
 
515
739
dropped:
516
740
        kfree_skb(skb);
517
741
out:
 
742
        if (curr_softif_neigh)
 
743
                softif_neigh_free_ref(curr_softif_neigh);
518
744
        return;
519
745
}
520
746
 
548
774
        dev->hard_start_xmit = interface_tx;
549
775
#endif
550
776
        dev->destructor = free_netdev;
 
777
        dev->tx_queue_len = 0;
551
778
 
552
779
        /**
553
780
         * can't call min_mtu, because the needed variables
554
781
         * have not been initialized yet
555
782
         */
556
783
        dev->mtu = ETH_DATA_LEN;
557
 
        dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
558
 
                                                * skbuff for our header */
 
784
        /* reserve more space in the skbuff for our header */
 
785
        dev->hard_header_len = BAT_HEADER_LEN;
559
786
 
560
787
        /* generate random address */
561
788
        random_ether_addr(dev_addr);
580
807
                goto out;
581
808
        }
582
809
 
583
 
        ret = register_netdev(soft_iface);
 
810
        ret = register_netdevice(soft_iface);
584
811
        if (ret < 0) {
585
812
                pr_err("Unable to register the batman interface '%s': %i\n",
586
813
                       name, ret);
604
831
 
605
832
        atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
606
833
        atomic_set(&bat_priv->bcast_seqno, 1);
607
 
        atomic_set(&bat_priv->hna_local_changed, 0);
 
834
        atomic_set(&bat_priv->tt_local_changed, 0);
608
835
 
609
836
        bat_priv->primary_if = NULL;
610
837
        bat_priv->num_ifaces = 0;
611
 
        bat_priv->softif_neigh = NULL;
612
838
 
613
839
        ret = sysfs_add_meshif(soft_iface);
614
840
        if (ret < 0)
646
872
        unregister_netdevice(soft_iface);
647
873
}
648
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
 
649
888
/* ethtool */
650
889
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
651
890
{
652
891
        cmd->supported = 0;
653
892
        cmd->advertising = 0;
654
 
        cmd->speed = SPEED_10;
 
893
        ethtool_cmd_speed_set(cmd, SPEED_10);
655
894
        cmd->duplex = DUPLEX_FULL;
656
895
        cmd->port = PORT_TP;
657
896
        cmd->phy_address = 0;
686
925
        return 1;
687
926
}
688
927
 
689
 
static u32 bat_get_rx_csum(struct net_device *dev)
690
 
{
691
 
        return 0;
692
 
}
693
 
 
694
 
static int bat_set_rx_csum(struct net_device *dev, u32 data)
695
 
{
696
 
        return -EOPNOTSUPP;
697
 
}