Merge branch 'slab/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / batman-adv / soft-interface.c
CommitLineData
5beef3c9 1/*
9b6d10b7 2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
5beef3c9
AL
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"
6a0e9fa8
ML
25#include "routing.h"
26#include "send.h"
27#include "bat_debugfs.h"
5beef3c9 28#include "translation-table.h"
6a0e9fa8
ML
29#include "types.h"
30#include "hash.h"
24c76fc0 31#include "send.h"
6a0e9fa8 32#include "bat_sysfs.h"
5a0e3ad6 33#include <linux/slab.h>
5beef3c9
AL
34#include <linux/ethtool.h>
35#include <linux/etherdevice.h>
24c76fc0 36#include "unicast.h"
5beef3c9 37
5beef3c9 38
5beef3c9
AL
39static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
40static void bat_get_drvinfo(struct net_device *dev,
41 struct ethtool_drvinfo *info);
42static u32 bat_get_msglevel(struct net_device *dev);
43static void bat_set_msglevel(struct net_device *dev, u32 value);
44static u32 bat_get_link(struct net_device *dev);
45static u32 bat_get_rx_csum(struct net_device *dev);
46static int bat_set_rx_csum(struct net_device *dev, u32 data);
47
48static const struct ethtool_ops bat_ethtool_ops = {
49 .get_settings = bat_get_settings,
50 .get_drvinfo = bat_get_drvinfo,
51 .get_msglevel = bat_get_msglevel,
52 .set_msglevel = bat_set_msglevel,
53 .get_link = bat_get_link,
54 .get_rx_csum = bat_get_rx_csum,
55 .set_rx_csum = bat_set_rx_csum
56};
57
99eed284 58int my_skb_head_push(struct sk_buff *skb, unsigned int len)
5beef3c9 59{
99eed284 60 int result;
5beef3c9 61
99eed284
SE
62 /**
63 * TODO: We must check if we can release all references to non-payload
64 * data using skb_header_release in our skbs to allow skb_cow_header to
65 * work optimally. This means that those skbs are not allowed to read
66 * or write any data which is before the current position of skb->data
67 * after that call and thus allow other skbs with the same data buffer
68 * to write freely in that area.
69 */
70 result = skb_cow_head(skb, len);
99eed284
SE
71 if (result < 0)
72 return result;
5beef3c9
AL
73
74 skb_push(skb, len);
75 return 0;
76}
77
42fa1b92 78static int interface_open(struct net_device *dev)
5beef3c9
AL
79{
80 netif_start_queue(dev);
81 return 0;
82}
83
42fa1b92 84static int interface_release(struct net_device *dev)
5beef3c9
AL
85{
86 netif_stop_queue(dev);
87 return 0;
88}
89
42fa1b92 90static struct net_device_stats *interface_stats(struct net_device *dev)
5beef3c9 91{
6a0e9fa8
ML
92 struct bat_priv *bat_priv = netdev_priv(dev);
93 return &bat_priv->stats;
5beef3c9
AL
94}
95
42fa1b92 96static int interface_set_mac_addr(struct net_device *dev, void *p)
5beef3c9 97{
6a0e9fa8 98 struct bat_priv *bat_priv = netdev_priv(dev);
a9c2910a
AL
99 struct sockaddr *addr = p;
100
101 if (!is_valid_ether_addr(addr->sa_data))
102 return -EADDRNOTAVAIL;
103
adaaa0c6 104 /* only modify hna-table if it has been initialised before */
8c70f138 105 if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
6a0e9fa8
ML
106 hna_local_remove(bat_priv, dev->dev_addr,
107 "mac address changed");
108 hna_local_add(dev, addr->sa_data);
adaaa0c6
LL
109 }
110
a9c2910a 111 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
a9c2910a
AL
112
113 return 0;
5beef3c9
AL
114}
115
42fa1b92 116static int interface_change_mtu(struct net_device *dev, int new_mtu)
5beef3c9
AL
117{
118 /* check ranges */
6a0e9fa8 119 if ((new_mtu < 68) || (new_mtu > hardif_min_mtu(dev)))
5beef3c9
AL
120 return -EINVAL;
121
122 dev->mtu = new_mtu;
123
124 return 0;
125}
126
6a0e9fa8 127int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
5beef3c9 128{
5beef3c9 129 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
6a0e9fa8 130 struct bat_priv *bat_priv = netdev_priv(soft_iface);
24c76fc0
ML
131 struct bcast_packet *bcast_packet;
132 int data_len = skb->len, ret;
5beef3c9 133
8c70f138 134 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
5beef3c9
AL
135 goto dropped;
136
6a0e9fa8
ML
137 soft_iface->trans_start = jiffies;
138
5beef3c9 139 /* TODO: check this for locks */
6a0e9fa8 140 hna_local_add(soft_iface, ethhdr->h_source);
5beef3c9
AL
141
142 /* ethernet packet should be broadcasted */
143 if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) {
8c70f138
ML
144 if (!bat_priv->primary_if)
145 goto dropped;
5beef3c9 146
99eed284 147 if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
5beef3c9
AL
148 goto dropped;
149
150 bcast_packet = (struct bcast_packet *)skb->data;
5beef3c9 151 bcast_packet->version = COMPAT_VERSION;
cf2d72ec 152 bcast_packet->ttl = TTL;
5beef3c9
AL
153
154 /* batman packet type: broadcast */
155 bcast_packet->packet_type = BAT_BCAST;
156
157 /* hw address of first interface is the orig mac because only
158 * this mac is known throughout the mesh */
8c70f138
ML
159 memcpy(bcast_packet->orig,
160 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
e7017195 161
5beef3c9 162 /* set broadcast sequence number */
8c70f138
ML
163 bcast_packet->seqno =
164 htonl(atomic_inc_return(&bat_priv->bcast_seqno));
5beef3c9 165
8c70f138 166 add_bcast_packet_to_list(bat_priv, skb);
5beef3c9 167
e7017195
SW
168 /* a copy is stored in the bcast list, therefore removing
169 * the original skb. */
170 kfree_skb(skb);
5beef3c9
AL
171
172 /* unicast packet */
173 } else {
24c76fc0 174 ret = unicast_send_skb(skb, bat_priv);
8c70f138
ML
175 if (ret != 0)
176 goto dropped_freed;
5beef3c9
AL
177 }
178
24c76fc0
ML
179 bat_priv->stats.tx_packets++;
180 bat_priv->stats.tx_bytes += data_len;
5beef3c9
AL
181 goto end;
182
5beef3c9 183dropped:
7d02d777 184 kfree_skb(skb);
8c70f138
ML
185dropped_freed:
186 bat_priv->stats.tx_dropped++;
5beef3c9 187end:
abad5446 188 return NETDEV_TX_OK;
5beef3c9
AL
189}
190
6a0e9fa8
ML
191void interface_rx(struct net_device *soft_iface,
192 struct sk_buff *skb, int hdr_size)
5beef3c9 193{
6a0e9fa8 194 struct bat_priv *priv = netdev_priv(soft_iface);
5beef3c9 195
e7017195 196 /* check if enough space is available for pulling, and pull */
b6faaae1
ML
197 if (!pskb_may_pull(skb, hdr_size))
198 goto dropped;
199
e7017195
SW
200 skb_pull_rcsum(skb, hdr_size);
201/* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
5beef3c9 202
b001f71e 203 /* skb->dev & skb->pkt_type are set here */
b6faaae1
ML
204 if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
205 goto dropped;
6a0e9fa8 206 skb->protocol = eth_type_trans(skb, soft_iface);
e7017195
SW
207
208 /* should not be neccesary anymore as we use skb_pull_rcsum()
209 * TODO: please verify this and remove this TODO
210 * -- Dec 21st 2009, Simon Wunderlich */
211
212/* skb->ip_summed = CHECKSUM_UNNECESSARY;*/
5beef3c9
AL
213
214 priv->stats.rx_packets++;
556c83ec 215 priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
5beef3c9 216
6a0e9fa8 217 soft_iface->last_rx = jiffies;
5beef3c9
AL
218
219 netif_rx(skb);
b6faaae1
ML
220 return;
221
222dropped:
223 kfree_skb(skb);
224 return;
5beef3c9
AL
225}
226
42fa1b92
SE
227#ifdef HAVE_NET_DEVICE_OPS
228static const struct net_device_ops bat_netdev_ops = {
229 .ndo_open = interface_open,
230 .ndo_stop = interface_release,
231 .ndo_get_stats = interface_stats,
232 .ndo_set_mac_address = interface_set_mac_addr,
233 .ndo_change_mtu = interface_change_mtu,
234 .ndo_start_xmit = interface_tx,
235 .ndo_validate_addr = eth_validate_addr
236};
237#endif
238
6a0e9fa8 239static void interface_setup(struct net_device *dev)
42fa1b92
SE
240{
241 struct bat_priv *priv = netdev_priv(dev);
242 char dev_addr[ETH_ALEN];
243
244 ether_setup(dev);
245
246#ifdef HAVE_NET_DEVICE_OPS
247 dev->netdev_ops = &bat_netdev_ops;
248#else
249 dev->open = interface_open;
250 dev->stop = interface_release;
251 dev->get_stats = interface_stats;
252 dev->set_mac_address = interface_set_mac_addr;
253 dev->change_mtu = interface_change_mtu;
254 dev->hard_start_xmit = interface_tx;
255#endif
256 dev->destructor = free_netdev;
257
6a0e9fa8
ML
258 /**
259 * can't call min_mtu, because the needed variables
260 * have not been initialized yet
261 */
262 dev->mtu = ETH_DATA_LEN;
42fa1b92
SE
263 dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
264 * skbuff for our header */
265
266 /* generate random address */
267 random_ether_addr(dev_addr);
268 memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
269
270 SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
271
272 memset(priv, 0, sizeof(struct bat_priv));
273}
274
6a0e9fa8
ML
275struct net_device *softif_create(char *name)
276{
277 struct net_device *soft_iface;
278 struct bat_priv *bat_priv;
279 int ret;
280
281 soft_iface = alloc_netdev(sizeof(struct bat_priv) , name,
282 interface_setup);
283
284 if (!soft_iface) {
285 pr_err("Unable to allocate the batman interface: %s\n", name);
286 goto out;
287 }
288
289 ret = register_netdev(soft_iface);
6a0e9fa8
ML
290 if (ret < 0) {
291 pr_err("Unable to register the batman interface '%s': %i\n",
292 name, ret);
293 goto free_soft_iface;
294 }
295
296 bat_priv = netdev_priv(soft_iface);
297
298 atomic_set(&bat_priv->aggregation_enabled, 1);
299 atomic_set(&bat_priv->bonding_enabled, 0);
300 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
301 atomic_set(&bat_priv->orig_interval, 1000);
302 atomic_set(&bat_priv->log_level, 0);
303 atomic_set(&bat_priv->frag_enabled, 1);
304 atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
305 atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
306
8c70f138
ML
307 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
308 atomic_set(&bat_priv->bcast_seqno, 1);
309 atomic_set(&bat_priv->hna_local_changed, 0);
310
6a0e9fa8
ML
311 bat_priv->primary_if = NULL;
312 bat_priv->num_ifaces = 0;
313
314 ret = sysfs_add_meshif(soft_iface);
6a0e9fa8
ML
315 if (ret < 0)
316 goto unreg_soft_iface;
317
318 ret = debugfs_add_meshif(soft_iface);
6a0e9fa8
ML
319 if (ret < 0)
320 goto unreg_sysfs;
321
8c70f138
ML
322 ret = mesh_init(soft_iface);
323 if (ret < 0)
324 goto unreg_debugfs;
325
6a0e9fa8
ML
326 return soft_iface;
327
8c70f138
ML
328unreg_debugfs:
329 debugfs_del_meshif(soft_iface);
6a0e9fa8
ML
330unreg_sysfs:
331 sysfs_del_meshif(soft_iface);
332unreg_soft_iface:
333 unregister_netdev(soft_iface);
334 return NULL;
335
336free_soft_iface:
337 free_netdev(soft_iface);
338out:
339 return NULL;
340}
341
342void softif_destroy(struct net_device *soft_iface)
343{
344 debugfs_del_meshif(soft_iface);
345 sysfs_del_meshif(soft_iface);
8c70f138 346 mesh_free(soft_iface);
6a0e9fa8
ML
347 unregister_netdevice(soft_iface);
348}
349
5beef3c9
AL
350/* ethtool */
351static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
352{
353 cmd->supported = 0;
354 cmd->advertising = 0;
355 cmd->speed = SPEED_10;
356 cmd->duplex = DUPLEX_FULL;
357 cmd->port = PORT_TP;
358 cmd->phy_address = 0;
359 cmd->transceiver = XCVR_INTERNAL;
360 cmd->autoneg = AUTONEG_DISABLE;
361 cmd->maxtxpkt = 0;
362 cmd->maxrxpkt = 0;
363
364 return 0;
365}
366
367static void bat_get_drvinfo(struct net_device *dev,
368 struct ethtool_drvinfo *info)
369{
370 strcpy(info->driver, "B.A.T.M.A.N. advanced");
371 strcpy(info->version, SOURCE_VERSION);
372 strcpy(info->fw_version, "N/A");
373 strcpy(info->bus_info, "batman");
374}
375
376static u32 bat_get_msglevel(struct net_device *dev)
377{
378 return -EOPNOTSUPP;
379}
380
381static void bat_set_msglevel(struct net_device *dev, u32 value)
382{
5beef3c9
AL
383}
384
385static u32 bat_get_link(struct net_device *dev)
386{
387 return 1;
388}
389
390static u32 bat_get_rx_csum(struct net_device *dev)
391{
392 return 0;
393}
394
395static int bat_set_rx_csum(struct net_device *dev, u32 data)
396{
397 return -EOPNOTSUPP;
398}