soft-interface.c 17.8 KB
Newer Older
1
/* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * Marek Lindner, Simon Wunderlich
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "main.h"
#include "soft-interface.h"
#include "hard-interface.h"
23
#include "distributed-arp-table.h"
24 25
#include "routing.h"
#include "send.h"
26
#include "debugfs.h"
27 28 29 30
#include "translation-table.h"
#include "hash.h"
#include "gateway_common.h"
#include "gateway_client.h"
31
#include "sysfs.h"
32
#include "originator.h"
33 34 35 36 37
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include "unicast.h"
38
#include "bridge_loop_avoidance.h"
39 40


41 42 43 44 45 46
static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
static void batadv_get_drvinfo(struct net_device *dev,
			       struct ethtool_drvinfo *info);
static u32 batadv_get_msglevel(struct net_device *dev);
static void batadv_set_msglevel(struct net_device *dev, u32 value);
static u32 batadv_get_link(struct net_device *dev);
47 48 49 50
static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data);
static void batadv_get_ethtool_stats(struct net_device *dev,
				     struct ethtool_stats *stats, u64 *data);
static int batadv_get_sset_count(struct net_device *dev, int stringset);
51

52 53 54 55 56 57
static const struct ethtool_ops batadv_ethtool_ops = {
	.get_settings = batadv_get_settings,
	.get_drvinfo = batadv_get_drvinfo,
	.get_msglevel = batadv_get_msglevel,
	.set_msglevel = batadv_set_msglevel,
	.get_link = batadv_get_link,
58 59 60
	.get_strings = batadv_get_strings,
	.get_ethtool_stats = batadv_get_ethtool_stats,
	.get_sset_count = batadv_get_sset_count,
61 62
};

63
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len)
64 65 66
{
	int result;

67
	/* TODO: We must check if we can release all references to non-payload
68 69 70 71 72 73 74 75 76 77 78 79 80 81
	 * data using skb_header_release in our skbs to allow skb_cow_header to
	 * work optimally. This means that those skbs are not allowed to read
	 * or write any data which is before the current position of skb->data
	 * after that call and thus allow other skbs with the same data buffer
	 * to write freely in that area.
	 */
	result = skb_cow_head(skb, len);
	if (result < 0)
		return result;

	skb_push(skb, len);
	return 0;
}

82
static int batadv_interface_open(struct net_device *dev)
83 84 85 86 87
{
	netif_start_queue(dev);
	return 0;
}

88
static int batadv_interface_release(struct net_device *dev)
89 90 91 92 93
{
	netif_stop_queue(dev);
	return 0;
}

94
static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
95
{
96
	struct batadv_priv *bat_priv = netdev_priv(dev);
97 98 99 100 101 102 103 104
	struct net_device_stats *stats = &bat_priv->stats;

	stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX);
	stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES);
	stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED);
	stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX);
	stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES);
	return stats;
105 106
}

107
static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
108
{
109
	struct batadv_priv *bat_priv = netdev_priv(dev);
110
	struct sockaddr *addr = p;
111
	uint8_t old_addr[ETH_ALEN];
112 113 114 115

	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

116 117 118
	memcpy(old_addr, dev->dev_addr, ETH_ALEN);
	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);

119
	/* only modify transtable if it has been initialized before */
120
	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) {
121
		batadv_tt_local_remove(bat_priv, old_addr,
122
				       "mac address changed", false);
123
		batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);
124 125
	}

126
	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
127 128 129
	return 0;
}

130
static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu)
131 132
{
	/* check ranges */
133
	if ((new_mtu < 68) || (new_mtu > batadv_hardif_min_mtu(dev)))
134 135 136 137 138 139 140
		return -EINVAL;

	dev->mtu = new_mtu;

	return 0;
}

141 142
static int batadv_interface_tx(struct sk_buff *skb,
			       struct net_device *soft_iface)
143 144
{
	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
145 146
	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
	struct batadv_hard_iface *primary_if = NULL;
147
	struct batadv_bcast_packet *bcast_packet;
148
	struct vlan_ethhdr *vhdr;
149
	__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
150 151 152 153
	static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
						   0x00, 0x00};
	static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
						    0x00, 0x00};
154
	unsigned int header_len = 0;
155
	int data_len = skb->len, ret;
156
	short vid __maybe_unused = -1;
157
	bool do_bcast = false;
158
	uint32_t seqno;
159
	unsigned long brd_delay = 1;
160

161
	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
162 163 164 165 166 167 168 169 170
		goto dropped;

	soft_iface->trans_start = jiffies;

	switch (ntohs(ethhdr->h_proto)) {
	case ETH_P_8021Q:
		vhdr = (struct vlan_ethhdr *)skb->data;
		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;

171
		if (vhdr->h_vlan_encapsulated_proto != ethertype)
172 173 174
			break;

		/* fall through */
175
	case BATADV_ETH_P_BATMAN:
176
		goto dropped;
177
	}
178

179
	if (batadv_bla_tx(bat_priv, skb, vid))
180 181
		goto dropped;

182
	/* Register the client MAC in the transtable */
183
	batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
184

185 186
	/* don't accept stp packets. STP does not help in meshes.
	 * better use the bridge loop avoidance ...
187 188 189
	 *
	 * The same goes for ECTP sent at least by some Cisco Switches,
	 * it might confuse the mesh when used with bridge loop avoidance.
190
	 */
191
	if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
192 193
		goto dropped;

194 195 196
	if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
		goto dropped;

197 198
	if (is_multicast_ether_addr(ethhdr->h_dest)) {
		do_bcast = true;
199

200
		switch (atomic_read(&bat_priv->gw_mode)) {
201
		case BATADV_GW_MODE_SERVER:
202
			/* gateway servers should not send dhcp
203 204
			 * requests into the mesh
			 */
205
			ret = batadv_gw_is_dhcp_target(skb, &header_len);
206 207 208
			if (ret)
				goto dropped;
			break;
209
		case BATADV_GW_MODE_CLIENT:
210
			/* gateway clients should send dhcp requests
211 212
			 * via unicast to their gateway
			 */
213
			ret = batadv_gw_is_dhcp_target(skb, &header_len);
214 215 216
			if (ret)
				do_bcast = false;
			break;
217
		case BATADV_GW_MODE_OFF:
218 219 220
		default:
			break;
		}
221 222 223 224
	}

	/* ethernet packet should be broadcasted */
	if (do_bcast) {
225
		primary_if = batadv_primary_if_get_selected(bat_priv);
226
		if (!primary_if)
227 228
			goto dropped;

229 230 231 232 233 234 235
		/* in case of ARP request, we do not immediately broadcasti the
		 * packet, instead we first wait for DAT to try to retrieve the
		 * correct ARP entry
		 */
		if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
			brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);

236
		if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
237 238
			goto dropped;

239
		bcast_packet = (struct batadv_bcast_packet *)skb->data;
240
		bcast_packet->header.version = BATADV_COMPAT_VERSION;
241
		bcast_packet->header.ttl = BATADV_TTL;
242 243

		/* batman packet type: broadcast */
244
		bcast_packet->header.packet_type = BATADV_BCAST;
245
		bcast_packet->reserved = 0;
246 247

		/* hw address of first interface is the orig mac because only
248 249
		 * this mac is known throughout the mesh
		 */
250
		memcpy(bcast_packet->orig,
251
		       primary_if->net_dev->dev_addr, ETH_ALEN);
252 253

		/* set broadcast sequence number */
254 255
		seqno = atomic_inc_return(&bat_priv->bcast_seqno);
		bcast_packet->seqno = htonl(seqno);
256

257
		batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay);
258 259

		/* a copy is stored in the bcast list, therefore removing
260 261
		 * the original skb.
		 */
262 263 264 265
		kfree_skb(skb);

	/* unicast packet */
	} else {
266
		if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
267
			ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
268 269 270 271
			if (ret)
				goto dropped;
		}

272 273 274 275 276
		if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
			goto dropped;

		batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);

277
		ret = batadv_unicast_send_skb(bat_priv, skb);
278 279 280 281
		if (ret != 0)
			goto dropped_freed;
	}

282 283
	batadv_inc_counter(bat_priv, BATADV_CNT_TX);
	batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len);
284 285 286 287 288
	goto end;

dropped:
	kfree_skb(skb);
dropped_freed:
289
	batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED);
290
end:
291
	if (primary_if)
292
		batadv_hardif_free_ref(primary_if);
293 294 295
	return NETDEV_TX_OK;
}

296
void batadv_interface_rx(struct net_device *soft_iface,
297
			 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
298
			 int hdr_size, struct batadv_orig_node *orig_node)
299
{
300
	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
301 302
	struct ethhdr *ethhdr;
	struct vlan_ethhdr *vhdr;
303
	struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
304
	short vid __maybe_unused = -1;
305
	__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
306 307
	bool is_bcast;

308
	is_bcast = (batadv_header->packet_type == BATADV_BCAST);
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

	/* check if enough space is available for pulling, and pull */
	if (!pskb_may_pull(skb, hdr_size))
		goto dropped;

	skb_pull_rcsum(skb, hdr_size);
	skb_reset_mac_header(skb);

	ethhdr = (struct ethhdr *)skb_mac_header(skb);

	switch (ntohs(ethhdr->h_proto)) {
	case ETH_P_8021Q:
		vhdr = (struct vlan_ethhdr *)skb->data;
		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;

324
		if (vhdr->h_vlan_encapsulated_proto != ethertype)
325 326 327
			break;

		/* fall through */
328
	case BATADV_ETH_P_BATMAN:
329 330 331 332 333 334 335 336
		goto dropped;
	}

	/* skb->dev & skb->pkt_type are set here */
	if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
		goto dropped;
	skb->protocol = eth_type_trans(skb, soft_iface);

L
Lucas De Marchi 已提交
337
	/* should not be necessary anymore as we use skb_pull_rcsum()
338
	 * TODO: please verify this and remove this TODO
339 340
	 * -- Dec 21st 2009, Simon Wunderlich
	 */
341

342
	/* skb->ip_summed = CHECKSUM_UNNECESSARY; */
343

344 345 346
	batadv_inc_counter(bat_priv, BATADV_CNT_RX);
	batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
			   skb->len + ETH_HLEN);
347 348 349

	soft_iface->last_rx = jiffies;

350 351 352 353 354 355
	/* Let the bridge loop avoidance check the packet. If will
	 * not handle it, we can safely push it up.
	 */
	if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
		goto out;

356 357 358 359
	if (orig_node)
		batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
						     ethhdr->h_source);

360
	if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
361 362
		goto dropped;

363
	netif_rx(skb);
364
	goto out;
365 366 367 368 369 370 371

dropped:
	kfree_skb(skb);
out:
	return;
}

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
/* batman-adv network devices have devices nesting below it and are a special
 * "super class" of normal network devices; split their locks off into a
 * separate class since they always nest.
 */
static struct lock_class_key batadv_netdev_xmit_lock_key;
static struct lock_class_key batadv_netdev_addr_lock_key;

/**
 * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue
 * @dev: device which owns the tx queue
 * @txq: tx queue to modify
 * @_unused: always NULL
 */
static void batadv_set_lockdep_class_one(struct net_device *dev,
					 struct netdev_queue *txq,
					 void *_unused)
{
	lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
}

/**
 * batadv_set_lockdep_class - Set txq and addr_list lockdep class
 * @dev: network device to modify
 */
static void batadv_set_lockdep_class(struct net_device *dev)
{
	lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
	netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
}

/**
 * batadv_softif_init - Late stage initialization of soft interface
 * @dev: registered network device to modify
 *
 * Returns error code on failures
 */
static int batadv_softif_init(struct net_device *dev)
{
	batadv_set_lockdep_class(dev);

	return 0;
}

415
static const struct net_device_ops batadv_netdev_ops = {
416
	.ndo_init = batadv_softif_init,
417 418 419 420 421 422
	.ndo_open = batadv_interface_open,
	.ndo_stop = batadv_interface_release,
	.ndo_get_stats = batadv_interface_stats,
	.ndo_set_mac_address = batadv_interface_set_mac_addr,
	.ndo_change_mtu = batadv_interface_change_mtu,
	.ndo_start_xmit = batadv_interface_tx,
423 424 425
	.ndo_validate_addr = eth_validate_addr
};

426
static void batadv_interface_setup(struct net_device *dev)
427
{
428
	struct batadv_priv *priv = netdev_priv(dev);
429 430 431

	ether_setup(dev);

432
	dev->netdev_ops = &batadv_netdev_ops;
433
	dev->destructor = free_netdev;
434
	dev->tx_queue_len = 0;
435

436
	/* can't call min_mtu, because the needed variables
437 438 439
	 * have not been initialized yet
	 */
	dev->mtu = ETH_DATA_LEN;
440
	/* reserve more space in the skbuff for our header */
441
	dev->hard_header_len = BATADV_HEADER_LEN;
442 443

	/* generate random address */
444
	eth_hw_addr_random(dev);
445

446
	SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
447

448
	memset(priv, 0, sizeof(*priv));
449 450
}

451
struct net_device *batadv_softif_create(const char *name)
452 453
{
	struct net_device *soft_iface;
454
	struct batadv_priv *bat_priv;
455
	int ret;
456
	size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
457

458 459
	soft_iface = alloc_netdev(sizeof(*bat_priv), name,
				  batadv_interface_setup);
460

461
	if (!soft_iface)
462 463
		goto out;

464 465 466 467 468 469 470 471 472
	bat_priv = netdev_priv(soft_iface);

	/* batadv_interface_stats() needs to be available as soon as
	 * register_netdevice() has been called
	 */
	bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
	if (!bat_priv->bat_counters)
		goto free_soft_iface;

473
	ret = register_netdevice(soft_iface);
474 475 476
	if (ret < 0) {
		pr_err("Unable to register the batman interface '%s': %i\n",
		       name, ret);
477
		goto free_bat_counters;
478 479 480 481
	}

	atomic_set(&bat_priv->aggregated_ogms, 1);
	atomic_set(&bat_priv->bonding, 0);
482
	atomic_set(&bat_priv->bridge_loop_avoidance, 0);
483 484 485
#ifdef CONFIG_BATMAN_ADV_DAT
	atomic_set(&bat_priv->distributed_arp_table, 1);
#endif
486
	atomic_set(&bat_priv->ap_isolation, 0);
487
	atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
488
	atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
489 490 491
	atomic_set(&bat_priv->gw_sel_class, 20);
	atomic_set(&bat_priv->gw_bandwidth, 41);
	atomic_set(&bat_priv->orig_interval, 1000);
492
	atomic_set(&bat_priv->hop_penalty, 30);
493 494
	atomic_set(&bat_priv->log_level, 0);
	atomic_set(&bat_priv->fragmentation, 1);
495 496
	atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN);
	atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN);
497

498
	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
499
	atomic_set(&bat_priv->bcast_seqno, 1);
500 501 502 503 504 505 506 507
	atomic_set(&bat_priv->tt.vn, 0);
	atomic_set(&bat_priv->tt.local_changes, 0);
	atomic_set(&bat_priv->tt.ogm_append_cnt, 0);
#ifdef CONFIG_BATMAN_ADV_BLA
	atomic_set(&bat_priv->bla.num_requests, 0);
#endif
	bat_priv->tt.last_changeset = NULL;
	bat_priv->tt.last_changeset_len = 0;
508 509 510 511

	bat_priv->primary_if = NULL;
	bat_priv->num_ifaces = 0;

512
	ret = batadv_algo_select(bat_priv, batadv_routing_algo);
513
	if (ret < 0)
514
		goto unreg_soft_iface;
515

516
	ret = batadv_sysfs_add_meshif(soft_iface);
517
	if (ret < 0)
518
		goto unreg_soft_iface;
519

520
	ret = batadv_debugfs_add_meshif(soft_iface);
521 522 523
	if (ret < 0)
		goto unreg_sysfs;

524
	ret = batadv_mesh_init(soft_iface);
525 526 527 528 529 530
	if (ret < 0)
		goto unreg_debugfs;

	return soft_iface;

unreg_debugfs:
531
	batadv_debugfs_del_meshif(soft_iface);
532
unreg_sysfs:
533
	batadv_sysfs_del_meshif(soft_iface);
534
unreg_soft_iface:
535
	free_percpu(bat_priv->bat_counters);
536
	unregister_netdevice(soft_iface);
537 538
	return NULL;

539 540
free_bat_counters:
	free_percpu(bat_priv->bat_counters);
541 542 543 544 545 546
free_soft_iface:
	free_netdev(soft_iface);
out:
	return NULL;
}

547
void batadv_softif_destroy(struct net_device *soft_iface)
548
{
549
	batadv_debugfs_del_meshif(soft_iface);
550
	batadv_sysfs_del_meshif(soft_iface);
551
	batadv_mesh_free(soft_iface);
552 553 554
	unregister_netdevice(soft_iface);
}

555
int batadv_softif_is_valid(const struct net_device *net_dev)
556
{
557
	if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx)
558 559 560 561 562
		return 1;

	return 0;
}

563
/* ethtool */
564
static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
565 566 567
{
	cmd->supported = 0;
	cmd->advertising = 0;
568
	ethtool_cmd_speed_set(cmd, SPEED_10);
569 570 571 572 573 574 575 576 577 578 579
	cmd->duplex = DUPLEX_FULL;
	cmd->port = PORT_TP;
	cmd->phy_address = 0;
	cmd->transceiver = XCVR_INTERNAL;
	cmd->autoneg = AUTONEG_DISABLE;
	cmd->maxtxpkt = 0;
	cmd->maxrxpkt = 0;

	return 0;
}

580 581
static void batadv_get_drvinfo(struct net_device *dev,
			       struct ethtool_drvinfo *info)
582 583
{
	strcpy(info->driver, "B.A.T.M.A.N. advanced");
584
	strcpy(info->version, BATADV_SOURCE_VERSION);
585 586 587 588
	strcpy(info->fw_version, "N/A");
	strcpy(info->bus_info, "batman");
}

589
static u32 batadv_get_msglevel(struct net_device *dev)
590 591 592 593
{
	return -EOPNOTSUPP;
}

594
static void batadv_set_msglevel(struct net_device *dev, u32 value)
595 596 597
{
}

598
static u32 batadv_get_link(struct net_device *dev)
599 600 601
{
	return 1;
}
602 603 604 605 606 607 608

/* Inspired by drivers/net/ethernet/dlink/sundance.c:1702
 * Declare each description string in struct.name[] to get fixed sized buffer
 * and compile time checking for strings longer than ETH_GSTRING_LEN.
 */
static const struct {
	const char name[ETH_GSTRING_LEN];
609
} batadv_counters_strings[] = {
610 611 612 613 614
	{ "tx" },
	{ "tx_bytes" },
	{ "tx_dropped" },
	{ "rx" },
	{ "rx_bytes" },
615 616 617 618 619 620 621 622 623 624 625 626
	{ "forward" },
	{ "forward_bytes" },
	{ "mgmt_tx" },
	{ "mgmt_tx_bytes" },
	{ "mgmt_rx" },
	{ "mgmt_rx_bytes" },
	{ "tt_request_tx" },
	{ "tt_request_rx" },
	{ "tt_response_tx" },
	{ "tt_response_rx" },
	{ "tt_roam_adv_tx" },
	{ "tt_roam_adv_rx" },
627 628 629 630 631 632 633
#ifdef CONFIG_BATMAN_ADV_DAT
	{ "dat_get_tx" },
	{ "dat_get_rx" },
	{ "dat_put_tx" },
	{ "dat_put_rx" },
	{ "dat_cached_reply_tx" },
#endif
634 635 636 637 638 639
};

static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
			       uint8_t *data)
{
	if (stringset == ETH_SS_STATS)
640 641
		memcpy(data, batadv_counters_strings,
		       sizeof(batadv_counters_strings));
642 643 644 645 646 647
}

static void batadv_get_ethtool_stats(struct net_device *dev,
				     struct ethtool_stats *stats,
				     uint64_t *data)
{
648
	struct batadv_priv *bat_priv = netdev_priv(dev);
649 650
	int i;

651
	for (i = 0; i < BATADV_CNT_NUM; i++)
652 653 654 655 656 657
		data[i] = batadv_sum_counter(bat_priv, i);
}

static int batadv_get_sset_count(struct net_device *dev, int stringset)
{
	if (stringset == ETH_SS_STATS)
658
		return BATADV_CNT_NUM;
659 660 661

	return -EOPNOTSUPP;
}