soft-interface.c 17.6 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
	if (orig_node)
		batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
						     ethhdr->h_source);

354
	if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
355 356
		goto dropped;

357 358 359
	/* Let the bridge loop avoidance check the packet. If will
	 * not handle it, we can safely push it up.
	 */
360
	if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
361 362
		goto out;

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
	atomic_set(&bat_priv->ap_isolation, 0);
484
	atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
485
	atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
486 487 488
	atomic_set(&bat_priv->gw_sel_class, 20);
	atomic_set(&bat_priv->gw_bandwidth, 41);
	atomic_set(&bat_priv->orig_interval, 1000);
489
	atomic_set(&bat_priv->hop_penalty, 30);
490 491
	atomic_set(&bat_priv->log_level, 0);
	atomic_set(&bat_priv->fragmentation, 1);
492 493
	atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN);
	atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN);
494

495
	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
496
	atomic_set(&bat_priv->bcast_seqno, 1);
497 498 499 500 501 502 503 504 505
	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;
	bat_priv->tt.poss_change = false;
506 507 508 509

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

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

514
	ret = batadv_sysfs_add_meshif(soft_iface);
515
	if (ret < 0)
516
		goto unreg_soft_iface;
517

518
	ret = batadv_debugfs_add_meshif(soft_iface);
519 520 521
	if (ret < 0)
		goto unreg_sysfs;

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

	return soft_iface;

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

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

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

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

	return 0;
}

561
/* ethtool */
562
static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
563 564 565
{
	cmd->supported = 0;
	cmd->advertising = 0;
566
	ethtool_cmd_speed_set(cmd, SPEED_10);
567 568 569 570 571 572 573 574 575 576 577
	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;
}

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

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

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

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

/* 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];
607
} batadv_counters_strings[] = {
608 609 610 611 612
	{ "tx" },
	{ "tx_bytes" },
	{ "tx_dropped" },
	{ "rx" },
	{ "rx_bytes" },
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
	{ "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" },
};

static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
			       uint8_t *data)
{
	if (stringset == ETH_SS_STATS)
631 632
		memcpy(data, batadv_counters_strings,
		       sizeof(batadv_counters_strings));
633 634 635 636 637 638
}

static void batadv_get_ethtool_stats(struct net_device *dev,
				     struct ethtool_stats *stats,
				     uint64_t *data)
{
639
	struct batadv_priv *bat_priv = netdev_priv(dev);
640 641
	int i;

642
	for (i = 0; i < BATADV_CNT_NUM; i++)
643 644 645 646 647 648
		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)
649
		return BATADV_CNT_NUM;
650 651 652

	return -EOPNOTSUPP;
}