xref: /linux/net/batman-adv/soft-interface.c (revision 64afe35398269577ef9809474dd7dc0e5d265176)
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 "types.h"
30 #include "hash.h"
31 #include "gateway_common.h"
32 #include "gateway_client.h"
33 #include "send.h"
34 #include "bat_sysfs.h"
35 #include <linux/slab.h>
36 #include <linux/ethtool.h>
37 #include <linux/etherdevice.h>
38 #include <linux/if_vlan.h>
39 #include "unicast.h"
40 #include "routing.h"
41 
42 
43 static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
44 static void bat_get_drvinfo(struct net_device *dev,
45 			    struct ethtool_drvinfo *info);
46 static u32 bat_get_msglevel(struct net_device *dev);
47 static void bat_set_msglevel(struct net_device *dev, u32 value);
48 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 
52 static const struct ethtool_ops bat_ethtool_ops = {
53 	.get_settings = bat_get_settings,
54 	.get_drvinfo = bat_get_drvinfo,
55 	.get_msglevel = bat_get_msglevel,
56 	.set_msglevel = bat_set_msglevel,
57 	.get_link = bat_get_link,
58 	.get_rx_csum = bat_get_rx_csum,
59 	.set_rx_csum = bat_set_rx_csum
60 };
61 
62 int my_skb_head_push(struct sk_buff *skb, unsigned int len)
63 {
64 	int result;
65 
66 	/**
67 	 * TODO: We must check if we can release all references to non-payload
68 	 * data using skb_header_release in our skbs to allow skb_cow_header to
69 	 * work optimally. This means that those skbs are not allowed to read
70 	 * or write any data which is before the current position of skb->data
71 	 * after that call and thus allow other skbs with the same data buffer
72 	 * to write freely in that area.
73 	 */
74 	result = skb_cow_head(skb, len);
75 	if (result < 0)
76 		return result;
77 
78 	skb_push(skb, len);
79 	return 0;
80 }
81 
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;
101 	struct hlist_node *node, *node_tmp;
102 
103 	spin_lock_bh(&bat_priv->softif_neigh_lock);
104 
105 	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 
113 		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);
127 	}
128 
129 	spin_unlock_bh(&bat_priv->softif_neigh_lock);
130 }
131 
132 static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
133 					     uint8_t *addr, short vid)
134 {
135 	struct softif_neigh *softif_neigh;
136 	struct hlist_node *node;
137 
138 	rcu_read_lock();
139 	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)
142 			continue;
143 
144 		if (softif_neigh->vid != vid)
145 			continue;
146 
147 		softif_neigh->last_seen = jiffies;
148 		goto found;
149 	}
150 
151 	softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
152 	if (!softif_neigh)
153 		goto out;
154 
155 	memcpy(softif_neigh->addr, addr, ETH_ALEN);
156 	softif_neigh->vid = vid;
157 	softif_neigh->last_seen = jiffies;
158 	kref_init(&softif_neigh->refcount);
159 
160 	INIT_HLIST_NODE(&softif_neigh->list);
161 	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;
170 }
171 
172 int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
173 {
174 	struct net_device *net_dev = (struct net_device *)seq->private;
175 	struct bat_priv *bat_priv = netdev_priv(net_dev);
176 	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);
185 	}
186 
187 	seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
188 
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;
217 }
218 
219 static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
220 			       short vid)
221 {
222 	struct bat_priv *bat_priv = netdev_priv(dev);
223 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
224 	struct batman_packet *batman_packet;
225 	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
226 
227 	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
228 		batman_packet = (struct batman_packet *)
229 					(skb->data + ETH_HLEN + VLAN_HLEN);
230 	else
231 		batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
232 
233 	if (batman_packet->version != COMPAT_VERSION)
234 		goto err;
235 
236 	if (batman_packet->packet_type != BAT_PACKET)
237 		goto err;
238 
239 	if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
240 		goto err;
241 
242 	if (is_my_mac(batman_packet->orig))
243 		goto err;
244 
245 	softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
246 
247 	if (!softif_neigh)
248 		goto err;
249 
250 	if (bat_priv->softif_neigh == softif_neigh)
251 		goto out;
252 
253 	/* we got a neighbor but its mac is 'bigger' than ours  */
254 	if (memcmp(bat_priv->primary_if->net_dev->dev_addr,
255 		   softif_neigh->addr, ETH_ALEN) < 0)
256 		goto out;
257 
258 	/* 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 	}
286 
287 out:
288 	kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
289 err:
290 	kfree_skb(skb);
291 	return;
292 }
293 
294 static int interface_open(struct net_device *dev)
295 {
296 	netif_start_queue(dev);
297 	return 0;
298 }
299 
300 static int interface_release(struct net_device *dev)
301 {
302 	netif_stop_queue(dev);
303 	return 0;
304 }
305 
306 static struct net_device_stats *interface_stats(struct net_device *dev)
307 {
308 	struct bat_priv *bat_priv = netdev_priv(dev);
309 	return &bat_priv->stats;
310 }
311 
312 static int interface_set_mac_addr(struct net_device *dev, void *p)
313 {
314 	struct bat_priv *bat_priv = netdev_priv(dev);
315 	struct sockaddr *addr = p;
316 
317 	if (!is_valid_ether_addr(addr->sa_data))
318 		return -EADDRNOTAVAIL;
319 
320 	/* only modify hna-table if it has been initialised before */
321 	if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
322 		hna_local_remove(bat_priv, dev->dev_addr,
323 				 "mac address changed");
324 		hna_local_add(dev, addr->sa_data);
325 	}
326 
327 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
328 	return 0;
329 }
330 
331 static int interface_change_mtu(struct net_device *dev, int new_mtu)
332 {
333 	/* check ranges */
334 	if ((new_mtu < 68) || (new_mtu > hardif_min_mtu(dev)))
335 		return -EINVAL;
336 
337 	dev->mtu = new_mtu;
338 
339 	return 0;
340 }
341 
342 int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
343 {
344 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
345 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
346 	struct bcast_packet *bcast_packet;
347 	struct vlan_ethhdr *vhdr;
348 	int data_len = skb->len, ret;
349 	short vid = -1;
350 	bool do_bcast = false;
351 
352 	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
353 		goto dropped;
354 
355 	soft_iface->trans_start = jiffies;
356 
357 	switch (ntohs(ethhdr->h_proto)) {
358 	case ETH_P_8021Q:
359 		vhdr = (struct vlan_ethhdr *)skb->data;
360 		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
361 
362 		if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
363 			break;
364 
365 		/* fall through */
366 	case ETH_P_BATMAN:
367 		softif_batman_recv(skb, soft_iface, vid);
368 		goto end;
369 	}
370 
371 	/**
372 	 * if we have a another chosen mesh exit node in range
373 	 * it will transport the packets to the mesh
374 	 */
375 	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid))
376 		goto dropped;
377 
378 	/* TODO: check this for locks */
379 	hna_local_add(soft_iface, ethhdr->h_source);
380 
381 	if (is_multicast_ether_addr(ethhdr->h_dest)) {
382 		ret = gw_is_target(bat_priv, skb);
383 
384 		if (ret < 0)
385 			goto dropped;
386 
387 		if (ret == 0)
388 			do_bcast = true;
389 	}
390 
391 	/* ethernet packet should be broadcasted */
392 	if (do_bcast) {
393 		if (!bat_priv->primary_if)
394 			goto dropped;
395 
396 		if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
397 			goto dropped;
398 
399 		bcast_packet = (struct bcast_packet *)skb->data;
400 		bcast_packet->version = COMPAT_VERSION;
401 		bcast_packet->ttl = TTL;
402 
403 		/* batman packet type: broadcast */
404 		bcast_packet->packet_type = BAT_BCAST;
405 
406 		/* hw address of first interface is the orig mac because only
407 		 * this mac is known throughout the mesh */
408 		memcpy(bcast_packet->orig,
409 		       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
410 
411 		/* set broadcast sequence number */
412 		bcast_packet->seqno =
413 			htonl(atomic_inc_return(&bat_priv->bcast_seqno));
414 
415 		add_bcast_packet_to_list(bat_priv, skb);
416 
417 		/* a copy is stored in the bcast list, therefore removing
418 		 * the original skb. */
419 		kfree_skb(skb);
420 
421 	/* unicast packet */
422 	} else {
423 		ret = unicast_send_skb(skb, bat_priv);
424 		if (ret != 0)
425 			goto dropped_freed;
426 	}
427 
428 	bat_priv->stats.tx_packets++;
429 	bat_priv->stats.tx_bytes += data_len;
430 	goto end;
431 
432 dropped:
433 	kfree_skb(skb);
434 dropped_freed:
435 	bat_priv->stats.tx_dropped++;
436 end:
437 	return NETDEV_TX_OK;
438 }
439 
440 void interface_rx(struct net_device *soft_iface,
441 		  struct sk_buff *skb, struct batman_if *recv_if,
442 		  int hdr_size)
443 {
444 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
445 	struct unicast_packet *unicast_packet;
446 	struct ethhdr *ethhdr;
447 	struct vlan_ethhdr *vhdr;
448 	short vid = -1;
449 	int ret;
450 
451 	/* check if enough space is available for pulling, and pull */
452 	if (!pskb_may_pull(skb, hdr_size))
453 		goto dropped;
454 
455 	skb_pull_rcsum(skb, hdr_size);
456 	skb_reset_mac_header(skb);
457 
458 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
459 
460 	switch (ntohs(ethhdr->h_proto)) {
461 	case ETH_P_8021Q:
462 		vhdr = (struct vlan_ethhdr *)skb->data;
463 		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
464 
465 		if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
466 			break;
467 
468 		/* fall through */
469 	case ETH_P_BATMAN:
470 		goto dropped;
471 	}
472 
473 	/**
474 	 * if we have a another chosen mesh exit node in range
475 	 * it will transport the packets to the non-mesh network
476 	 */
477 	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) {
478 		skb_push(skb, hdr_size);
479 		unicast_packet = (struct unicast_packet *)skb->data;
480 
481 		if ((unicast_packet->packet_type != BAT_UNICAST) &&
482 		    (unicast_packet->packet_type != BAT_UNICAST_FRAG))
483 			goto dropped;
484 
485 		skb_reset_mac_header(skb);
486 
487 		memcpy(unicast_packet->dest,
488 		       bat_priv->softif_neigh->addr, ETH_ALEN);
489 		ret = route_unicast_packet(skb, recv_if, hdr_size);
490 		if (ret == NET_RX_DROP)
491 			goto dropped;
492 
493 		goto out;
494 	}
495 
496 	/* skb->dev & skb->pkt_type are set here */
497 	if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
498 		goto dropped;
499 	skb->protocol = eth_type_trans(skb, soft_iface);
500 
501 	/* should not be neccesary anymore as we use skb_pull_rcsum()
502 	 * TODO: please verify this and remove this TODO
503 	 * -- Dec 21st 2009, Simon Wunderlich */
504 
505 /*	skb->ip_summed = CHECKSUM_UNNECESSARY;*/
506 
507 	bat_priv->stats.rx_packets++;
508 	bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
509 
510 	soft_iface->last_rx = jiffies;
511 
512 	netif_rx(skb);
513 	return;
514 
515 dropped:
516 	kfree_skb(skb);
517 out:
518 	return;
519 }
520 
521 #ifdef HAVE_NET_DEVICE_OPS
522 static const struct net_device_ops bat_netdev_ops = {
523 	.ndo_open = interface_open,
524 	.ndo_stop = interface_release,
525 	.ndo_get_stats = interface_stats,
526 	.ndo_set_mac_address = interface_set_mac_addr,
527 	.ndo_change_mtu = interface_change_mtu,
528 	.ndo_start_xmit = interface_tx,
529 	.ndo_validate_addr = eth_validate_addr
530 };
531 #endif
532 
533 static void interface_setup(struct net_device *dev)
534 {
535 	struct bat_priv *priv = netdev_priv(dev);
536 	char dev_addr[ETH_ALEN];
537 
538 	ether_setup(dev);
539 
540 #ifdef HAVE_NET_DEVICE_OPS
541 	dev->netdev_ops = &bat_netdev_ops;
542 #else
543 	dev->open = interface_open;
544 	dev->stop = interface_release;
545 	dev->get_stats = interface_stats;
546 	dev->set_mac_address = interface_set_mac_addr;
547 	dev->change_mtu = interface_change_mtu;
548 	dev->hard_start_xmit = interface_tx;
549 #endif
550 	dev->destructor = free_netdev;
551 
552 	/**
553 	 * can't call min_mtu, because the needed variables
554 	 * have not been initialized yet
555 	 */
556 	dev->mtu = ETH_DATA_LEN;
557 	dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
558 						* skbuff for our header */
559 
560 	/* generate random address */
561 	random_ether_addr(dev_addr);
562 	memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
563 
564 	SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
565 
566 	memset(priv, 0, sizeof(struct bat_priv));
567 }
568 
569 struct net_device *softif_create(char *name)
570 {
571 	struct net_device *soft_iface;
572 	struct bat_priv *bat_priv;
573 	int ret;
574 
575 	soft_iface = alloc_netdev(sizeof(struct bat_priv) , name,
576 				   interface_setup);
577 
578 	if (!soft_iface) {
579 		pr_err("Unable to allocate the batman interface: %s\n", name);
580 		goto out;
581 	}
582 
583 	ret = register_netdev(soft_iface);
584 	if (ret < 0) {
585 		pr_err("Unable to register the batman interface '%s': %i\n",
586 		       name, ret);
587 		goto free_soft_iface;
588 	}
589 
590 	bat_priv = netdev_priv(soft_iface);
591 
592 	atomic_set(&bat_priv->aggregated_ogms, 1);
593 	atomic_set(&bat_priv->bonding, 0);
594 	atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
595 	atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
596 	atomic_set(&bat_priv->gw_sel_class, 20);
597 	atomic_set(&bat_priv->gw_bandwidth, 41);
598 	atomic_set(&bat_priv->orig_interval, 1000);
599 	atomic_set(&bat_priv->hop_penalty, 10);
600 	atomic_set(&bat_priv->log_level, 0);
601 	atomic_set(&bat_priv->fragmentation, 1);
602 	atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
603 	atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
604 
605 	atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
606 	atomic_set(&bat_priv->bcast_seqno, 1);
607 	atomic_set(&bat_priv->hna_local_changed, 0);
608 
609 	bat_priv->primary_if = NULL;
610 	bat_priv->num_ifaces = 0;
611 	bat_priv->softif_neigh = NULL;
612 
613 	ret = sysfs_add_meshif(soft_iface);
614 	if (ret < 0)
615 		goto unreg_soft_iface;
616 
617 	ret = debugfs_add_meshif(soft_iface);
618 	if (ret < 0)
619 		goto unreg_sysfs;
620 
621 	ret = mesh_init(soft_iface);
622 	if (ret < 0)
623 		goto unreg_debugfs;
624 
625 	return soft_iface;
626 
627 unreg_debugfs:
628 	debugfs_del_meshif(soft_iface);
629 unreg_sysfs:
630 	sysfs_del_meshif(soft_iface);
631 unreg_soft_iface:
632 	unregister_netdev(soft_iface);
633 	return NULL;
634 
635 free_soft_iface:
636 	free_netdev(soft_iface);
637 out:
638 	return NULL;
639 }
640 
641 void softif_destroy(struct net_device *soft_iface)
642 {
643 	debugfs_del_meshif(soft_iface);
644 	sysfs_del_meshif(soft_iface);
645 	mesh_free(soft_iface);
646 	unregister_netdevice(soft_iface);
647 }
648 
649 /* ethtool */
650 static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
651 {
652 	cmd->supported = 0;
653 	cmd->advertising = 0;
654 	cmd->speed = SPEED_10;
655 	cmd->duplex = DUPLEX_FULL;
656 	cmd->port = PORT_TP;
657 	cmd->phy_address = 0;
658 	cmd->transceiver = XCVR_INTERNAL;
659 	cmd->autoneg = AUTONEG_DISABLE;
660 	cmd->maxtxpkt = 0;
661 	cmd->maxrxpkt = 0;
662 
663 	return 0;
664 }
665 
666 static void bat_get_drvinfo(struct net_device *dev,
667 			    struct ethtool_drvinfo *info)
668 {
669 	strcpy(info->driver, "B.A.T.M.A.N. advanced");
670 	strcpy(info->version, SOURCE_VERSION);
671 	strcpy(info->fw_version, "N/A");
672 	strcpy(info->bus_info, "batman");
673 }
674 
675 static u32 bat_get_msglevel(struct net_device *dev)
676 {
677 	return -EOPNOTSUPP;
678 }
679 
680 static void bat_set_msglevel(struct net_device *dev, u32 value)
681 {
682 }
683 
684 static u32 bat_get_link(struct net_device *dev)
685 {
686 	return 1;
687 }
688 
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 }
698