Blame view

net/batman-adv/soft-interface.c 21.6 KB
0b8739314   Antonio Quartulli   batman-adv: updat...
1
  /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * 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
c6c8fea29   Sven Eckelmann   net: Add batman-a...
18
19
20
21
22
   */
  
  #include "main.h"
  #include "soft-interface.h"
  #include "hard-interface.h"
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
23
  #include "distributed-arp-table.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
24
25
  #include "routing.h"
  #include "send.h"
b706b13b6   Sven Eckelmann   batman-adv: Remov...
26
  #include "debugfs.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
27
  #include "translation-table.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
28
29
30
  #include "hash.h"
  #include "gateway_common.h"
  #include "gateway_client.h"
b706b13b6   Sven Eckelmann   batman-adv: Remov...
31
  #include "sysfs.h"
43676ab59   Antonio Quartulli   batman-adv: impro...
32
  #include "originator.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
33
34
35
36
  #include <linux/slab.h>
  #include <linux/ethtool.h>
  #include <linux/etherdevice.h>
  #include <linux/if_vlan.h>
af5d4f773   Antonio Quartulli   batman-adv: use E...
37
  #include <linux/if_ether.h>
c6c8fea29   Sven Eckelmann   net: Add batman-a...
38
  #include "unicast.h"
23721387c   Simon Wunderlich   batman-adv: add b...
39
  #include "bridge_loop_avoidance.h"
d353d8d4d   Martin Hundebøll   batman-adv: netwo...
40
  #include "network-coding.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
41

0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
42
43
44
45
46
47
  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);
f8214865a   Martin Hundebøll   batman-adv: Add g...
48
49
50
51
  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);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
52

0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
53
54
55
56
57
58
  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,
f8214865a   Martin Hundebøll   batman-adv: Add g...
59
60
61
  	.get_strings = batadv_get_strings,
  	.get_ethtool_stats = batadv_get_ethtool_stats,
  	.get_sset_count = batadv_get_sset_count,
c6c8fea29   Sven Eckelmann   net: Add batman-a...
62
  };
04b482a21   Sven Eckelmann   batman-adv: Prefi...
63
  int batadv_skb_head_push(struct sk_buff *skb, unsigned int len)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
64
65
  {
  	int result;
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
66
  	/* TODO: We must check if we can release all references to non-payload
c6c8fea29   Sven Eckelmann   net: Add batman-a...
67
68
69
70
71
72
73
74
75
76
77
78
79
  	 * 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;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
80
  static int batadv_interface_open(struct net_device *dev)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
81
82
83
84
  {
  	netif_start_queue(dev);
  	return 0;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
85
  static int batadv_interface_release(struct net_device *dev)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
86
87
88
89
  {
  	netif_stop_queue(dev);
  	return 0;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
90
  static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
91
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
92
  	struct batadv_priv *bat_priv = netdev_priv(dev);
1c9b0550f   Marek Lindner   batman-adv: conve...
93
94
95
96
97
98
99
100
  	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;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
101
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
102
  static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
103
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
104
  	struct batadv_priv *bat_priv = netdev_priv(dev);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
105
  	struct sockaddr *addr = p;
40a3eb33e   Def   batman-adv: Fix c...
106
  	uint8_t old_addr[ETH_ALEN];
c6c8fea29   Sven Eckelmann   net: Add batman-a...
107
108
109
  
  	if (!is_valid_ether_addr(addr->sa_data))
  		return -EADDRNOTAVAIL;
40a3eb33e   Def   batman-adv: Fix c...
110
111
  	memcpy(old_addr, dev->dev_addr, ETH_ALEN);
  	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
015758d00   Antonio Quartulli   batman-adv: corre...
112
  	/* only modify transtable if it has been initialized before */
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
113
  	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) {
40a3eb33e   Def   batman-adv: Fix c...
114
  		batadv_tt_local_remove(bat_priv, old_addr,
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
115
  				       "mac address changed", false);
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
116
  		batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
117
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
118
119
  	return 0;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
120
  static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
121
122
  {
  	/* check ranges */
9563877ea   Sven Eckelmann   batman-adv: Prefi...
123
  	if ((new_mtu < 68) || (new_mtu > batadv_hardif_min_mtu(dev)))
c6c8fea29   Sven Eckelmann   net: Add batman-a...
124
125
126
127
128
129
  		return -EINVAL;
  
  	dev->mtu = new_mtu;
  
  	return 0;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
130
131
  static int batadv_interface_tx(struct sk_buff *skb,
  			       struct net_device *soft_iface)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
132
133
  {
  	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
134
135
  	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
  	struct batadv_hard_iface *primary_if = NULL;
964126901   Sven Eckelmann   batman-adv: Prefi...
136
  	struct batadv_bcast_packet *bcast_packet;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
137
  	struct vlan_ethhdr *vhdr;
af5d4f773   Antonio Quartulli   batman-adv: use E...
138
  	__be16 ethertype = __constant_htons(ETH_P_BATMAN);
4934ab951   Simon Wunderlich   batman-adv: don't...
139
140
141
142
  	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};
be7af5cf9   Marek Lindner   batman-adv: refac...
143
  	unsigned int header_len = 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
144
  	int data_len = skb->len, ret;
7a5cc2427   Simon Wunderlich   batman-adv: add b...
145
  	short vid __maybe_unused = -1;
be7af5cf9   Marek Lindner   batman-adv: refac...
146
  	bool do_bcast = false;
bbb1f90ef   Sven Eckelmann   batman-adv: Don't...
147
  	uint32_t seqno;
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
148
  	unsigned long brd_delay = 1;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
149

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
150
  	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
151
152
153
154
155
156
157
158
  		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;
7e071c79a   Sven Eckelmann   batman-adv: Prefi...
159
  		if (vhdr->h_vlan_encapsulated_proto != ethertype)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
160
161
162
  			break;
  
  		/* fall through */
af5d4f773   Antonio Quartulli   batman-adv: use E...
163
  	case ETH_P_BATMAN:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
164
  		goto dropped;
a7f6ee949   Simon Wunderlich   batman-adv: remov...
165
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
166

08adf1512   Sven Eckelmann   batman-adv: Prefi...
167
  	if (batadv_bla_tx(bat_priv, skb, vid))
23721387c   Simon Wunderlich   batman-adv: add b...
168
  		goto dropped;
a73105b8d   Antonio Quartulli   batman-adv: impro...
169
  	/* Register the client MAC in the transtable */
02233e0c7   Linus Lüssing   batman-adv: Do no...
170
171
  	if (!is_multicast_ether_addr(ethhdr->h_source))
  		batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
172

b1a8c04b8   Simon Wunderlich   batman-adv: drop ...
173
174
  	/* don't accept stp packets. STP does not help in meshes.
  	 * better use the bridge loop avoidance ...
4934ab951   Simon Wunderlich   batman-adv: don't...
175
176
177
  	 *
  	 * The same goes for ECTP sent at least by some Cisco Switches,
  	 * it might confuse the mesh when used with bridge loop avoidance.
b1a8c04b8   Simon Wunderlich   batman-adv: drop ...
178
  	 */
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
179
  	if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
b1a8c04b8   Simon Wunderlich   batman-adv: drop ...
180
  		goto dropped;
4934ab951   Simon Wunderlich   batman-adv: don't...
181
182
  	if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
  		goto dropped;
be7af5cf9   Marek Lindner   batman-adv: refac...
183
184
  	if (is_multicast_ether_addr(ethhdr->h_dest)) {
  		do_bcast = true;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
185

be7af5cf9   Marek Lindner   batman-adv: refac...
186
  		switch (atomic_read(&bat_priv->gw_mode)) {
cd646ab1e   Sven Eckelmann   batman-adv: Prefi...
187
  		case BATADV_GW_MODE_SERVER:
be7af5cf9   Marek Lindner   batman-adv: refac...
188
  			/* gateway servers should not send dhcp
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
189
190
  			 * requests into the mesh
  			 */
7cf06bc6f   Sven Eckelmann   batman-adv: Prefi...
191
  			ret = batadv_gw_is_dhcp_target(skb, &header_len);
be7af5cf9   Marek Lindner   batman-adv: refac...
192
193
194
  			if (ret)
  				goto dropped;
  			break;
cd646ab1e   Sven Eckelmann   batman-adv: Prefi...
195
  		case BATADV_GW_MODE_CLIENT:
be7af5cf9   Marek Lindner   batman-adv: refac...
196
  			/* gateway clients should send dhcp requests
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
197
198
  			 * via unicast to their gateway
  			 */
7cf06bc6f   Sven Eckelmann   batman-adv: Prefi...
199
  			ret = batadv_gw_is_dhcp_target(skb, &header_len);
be7af5cf9   Marek Lindner   batman-adv: refac...
200
201
202
  			if (ret)
  				do_bcast = false;
  			break;
cd646ab1e   Sven Eckelmann   batman-adv: Prefi...
203
  		case BATADV_GW_MODE_OFF:
be7af5cf9   Marek Lindner   batman-adv: refac...
204
205
206
  		default:
  			break;
  		}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
207
208
209
210
  	}
  
  	/* ethernet packet should be broadcasted */
  	if (do_bcast) {
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
211
  		primary_if = batadv_primary_if_get_selected(bat_priv);
32ae9b221   Marek Lindner   batman-adv: Make ...
212
  		if (!primary_if)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
213
  			goto dropped;
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
214
215
216
217
218
219
  		/* 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);
04b482a21   Sven Eckelmann   batman-adv: Prefi...
220
  		if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
221
  			goto dropped;
964126901   Sven Eckelmann   batman-adv: Prefi...
222
  		bcast_packet = (struct batadv_bcast_packet *)skb->data;
7e071c79a   Sven Eckelmann   batman-adv: Prefi...
223
  		bcast_packet->header.version = BATADV_COMPAT_VERSION;
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
224
  		bcast_packet->header.ttl = BATADV_TTL;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
225
226
  
  		/* batman packet type: broadcast */
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
227
  		bcast_packet->header.packet_type = BATADV_BCAST;
162d549c6   Sven Eckelmann   batman-adv: Don't...
228
  		bcast_packet->reserved = 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
229
230
  
  		/* hw address of first interface is the orig mac because only
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
231
232
  		 * this mac is known throughout the mesh
  		 */
c6c8fea29   Sven Eckelmann   net: Add batman-a...
233
  		memcpy(bcast_packet->orig,
32ae9b221   Marek Lindner   batman-adv: Make ...
234
  		       primary_if->net_dev->dev_addr, ETH_ALEN);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
235
236
  
  		/* set broadcast sequence number */
bbb1f90ef   Sven Eckelmann   batman-adv: Don't...
237
238
  		seqno = atomic_inc_return(&bat_priv->bcast_seqno);
  		bcast_packet->seqno = htonl(seqno);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
239

c384ea3ec   Antonio Quartulli   batman-adv: Distr...
240
  		batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
241
242
  
  		/* a copy is stored in the bcast list, therefore removing
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
243
244
  		 * the original skb.
  		 */
c6c8fea29   Sven Eckelmann   net: Add batman-a...
245
246
247
248
  		kfree_skb(skb);
  
  	/* unicast packet */
  	} else {
cd646ab1e   Sven Eckelmann   batman-adv: Prefi...
249
  		if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
7cf06bc6f   Sven Eckelmann   batman-adv: Prefi...
250
  			ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
be7af5cf9   Marek Lindner   batman-adv: refac...
251
252
253
  			if (ret)
  				goto dropped;
  		}
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
254
255
256
257
  		if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
  			goto dropped;
  
  		batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
7cdcf6ddd   Antonio Quartulli   batman-adv: add U...
258
  		ret = batadv_unicast_send_skb(bat_priv, skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
259
260
261
  		if (ret != 0)
  			goto dropped_freed;
  	}
1c9b0550f   Marek Lindner   batman-adv: conve...
262
263
  	batadv_inc_counter(bat_priv, BATADV_CNT_TX);
  	batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
264
265
266
267
268
  	goto end;
  
  dropped:
  	kfree_skb(skb);
  dropped_freed:
1c9b0550f   Marek Lindner   batman-adv: conve...
269
  	batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
270
  end:
32ae9b221   Marek Lindner   batman-adv: Make ...
271
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
272
  		batadv_hardif_free_ref(primary_if);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
273
274
  	return NETDEV_TX_OK;
  }
04b482a21   Sven Eckelmann   batman-adv: Prefi...
275
  void batadv_interface_rx(struct net_device *soft_iface,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
276
  			 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
371351731   Antonio Quartulli   batman-adv: chang...
277
  			 int hdr_size, struct batadv_orig_node *orig_node)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
278
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
279
  	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
280
281
  	struct ethhdr *ethhdr;
  	struct vlan_ethhdr *vhdr;
04c9f416e   David S. Miller   Merge git://git.k...
282
  	struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
7a5cc2427   Simon Wunderlich   batman-adv: add b...
283
  	short vid __maybe_unused = -1;
af5d4f773   Antonio Quartulli   batman-adv: use E...
284
  	__be16 ethertype = __constant_htons(ETH_P_BATMAN);
2d3f6ccc4   Simon Wunderlich   batman-adv: check...
285
  	bool is_bcast;
04c9f416e   David S. Miller   Merge git://git.k...
286
  	is_bcast = (batadv_header->packet_type == BATADV_BCAST);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  
  	/* 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;
7e071c79a   Sven Eckelmann   batman-adv: Prefi...
301
  		if (vhdr->h_vlan_encapsulated_proto != ethertype)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
302
303
304
  			break;
  
  		/* fall through */
af5d4f773   Antonio Quartulli   batman-adv: use E...
305
  	case ETH_P_BATMAN:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
306
307
  		goto dropped;
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
308
309
310
311
  	/* 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);
25985edce   Lucas De Marchi   Fix common misspe...
312
  	/* should not be necessary anymore as we use skb_pull_rcsum()
c6c8fea29   Sven Eckelmann   net: Add batman-a...
313
  	 * TODO: please verify this and remove this TODO
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
314
315
  	 * -- Dec 21st 2009, Simon Wunderlich
  	 */
c6c8fea29   Sven Eckelmann   net: Add batman-a...
316

9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
317
  	/* skb->ip_summed = CHECKSUM_UNNECESSARY; */
c6c8fea29   Sven Eckelmann   net: Add batman-a...
318

1c9b0550f   Marek Lindner   batman-adv: conve...
319
320
321
  	batadv_inc_counter(bat_priv, BATADV_CNT_RX);
  	batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
  			   skb->len + ETH_HLEN);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
322
323
  
  	soft_iface->last_rx = jiffies;
74490f969   Antonio Quartulli   batman-adv: proce...
324
325
326
327
328
  	/* 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;
371351731   Antonio Quartulli   batman-adv: chang...
329
330
331
  	if (orig_node)
  		batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
  						     ethhdr->h_source);
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
332
  	if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
59b699cde   Antonio Quartulli   batman-adv: imple...
333
  		goto dropped;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
334
  	netif_rx(skb);
ba85fac28   Simon Wunderlich   batman-adv: prote...
335
  	goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
336
337
338
339
340
341
  
  dropped:
  	kfree_skb(skb);
  out:
  	return;
  }
36c1d1531   Sven Eckelmann   batman-adv: Set s...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  /* 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);
  }
  
  /**
5bc44dc84   Simon Wunderlich   batman-adv: postp...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
   * batadv_softif_destroy_finish - cleans up the remains of a softif
   * @work: work queue item
   *
   * Free the parts of the soft interface which can not be removed under
   * rtnl lock (to prevent deadlock situations).
   */
  static void batadv_softif_destroy_finish(struct work_struct *work)
  {
  	struct batadv_priv *bat_priv;
  	struct net_device *soft_iface;
  
  	bat_priv = container_of(work, struct batadv_priv,
  				cleanup_work);
  	soft_iface = bat_priv->soft_iface;
5bc44dc84   Simon Wunderlich   batman-adv: postp...
387
388
389
390
391
392
  	batadv_sysfs_del_meshif(soft_iface);
  
  	rtnl_lock();
  	unregister_netdevice(soft_iface);
  	rtnl_unlock();
  }
37130293f   Sven Eckelmann   batman-adv: Move ...
393
394
395
396
397
398
399
  /**
   * batadv_softif_init_late - late stage initialization of soft interface
   * @dev: registered network device to modify
   *
   * Returns error code on failures
   */
  static int batadv_softif_init_late(struct net_device *dev)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
400
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
401
  	struct batadv_priv *bat_priv;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
402
  	int ret;
d69909d2f   Sven Eckelmann   batman-adv: Prefi...
403
  	size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
404

37130293f   Sven Eckelmann   batman-adv: Move ...
405
  	batadv_set_lockdep_class(dev);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
406

37130293f   Sven Eckelmann   batman-adv: Move ...
407
408
  	bat_priv = netdev_priv(dev);
  	bat_priv->soft_iface = dev;
5bc44dc84   Simon Wunderlich   batman-adv: postp...
409
  	INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
1c9b0550f   Marek Lindner   batman-adv: conve...
410
411
412
413
414
415
  
  	/* 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)
37130293f   Sven Eckelmann   batman-adv: Move ...
416
  		return -ENOMEM;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
417

c6c8fea29   Sven Eckelmann   net: Add batman-a...
418
419
  	atomic_set(&bat_priv->aggregated_ogms, 1);
  	atomic_set(&bat_priv->bonding, 0);
fa706554d   Antonio Quartulli   batman-adv: don't...
420
  #ifdef CONFIG_BATMAN_ADV_BLA
23721387c   Simon Wunderlich   batman-adv: add b...
421
  	atomic_set(&bat_priv->bridge_loop_avoidance, 0);
fa706554d   Antonio Quartulli   batman-adv: don't...
422
  #endif
33af49ad8   Antonio Quartulli   batman-adv: Distr...
423
424
425
  #ifdef CONFIG_BATMAN_ADV_DAT
  	atomic_set(&bat_priv->distributed_arp_table, 1);
  #endif
59b699cde   Antonio Quartulli   batman-adv: imple...
426
  	atomic_set(&bat_priv->ap_isolation, 0);
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
427
  	atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
cd646ab1e   Sven Eckelmann   batman-adv: Prefi...
428
  	atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
429
430
431
  	atomic_set(&bat_priv->gw_sel_class, 20);
  	atomic_set(&bat_priv->gw_bandwidth, 41);
  	atomic_set(&bat_priv->orig_interval, 1000);
8681a1c4d   Marek Lindner   batman-adv: encou...
432
  	atomic_set(&bat_priv->hop_penalty, 30);
0c430d0d7   Marek Lindner   batman-adv: unblo...
433
  #ifdef CONFIG_BATMAN_ADV_DEBUG
c6c8fea29   Sven Eckelmann   net: Add batman-a...
434
  	atomic_set(&bat_priv->log_level, 0);
0c430d0d7   Marek Lindner   batman-adv: unblo...
435
  #endif
c6c8fea29   Sven Eckelmann   net: Add batman-a...
436
  	atomic_set(&bat_priv->fragmentation, 1);
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
437
438
  	atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN);
  	atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
439

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
440
  	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
441
  	atomic_set(&bat_priv->bcast_seqno, 1);
807736f6e   Sven Eckelmann   batman-adv: Split...
442
443
444
445
446
447
448
449
  	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;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
450
451
452
  
  	bat_priv->primary_if = NULL;
  	bat_priv->num_ifaces = 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
453

d353d8d4d   Martin Hundebøll   batman-adv: netwo...
454
  	batadv_nc_init_bat_priv(bat_priv);
37130293f   Sven Eckelmann   batman-adv: Move ...
455
  	ret = batadv_algo_select(bat_priv, batadv_routing_algo);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
456
  	if (ret < 0)
37130293f   Sven Eckelmann   batman-adv: Move ...
457
  		goto free_bat_counters;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
458

37130293f   Sven Eckelmann   batman-adv: Move ...
459
  	ret = batadv_debugfs_add_meshif(dev);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
460
  	if (ret < 0)
37130293f   Sven Eckelmann   batman-adv: Move ...
461
  		goto free_bat_counters;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
462

37130293f   Sven Eckelmann   batman-adv: Move ...
463
  	ret = batadv_mesh_init(dev);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
464
465
  	if (ret < 0)
  		goto unreg_debugfs;
37130293f   Sven Eckelmann   batman-adv: Move ...
466
  	return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
467
468
  
  unreg_debugfs:
37130293f   Sven Eckelmann   batman-adv: Move ...
469
  	batadv_debugfs_del_meshif(dev);
1c9b0550f   Marek Lindner   batman-adv: conve...
470
471
  free_bat_counters:
  	free_percpu(bat_priv->bat_counters);
f69ae770e   Martin Hundebøll   batman-adv: Avoid...
472
  	bat_priv->bat_counters = NULL;
37130293f   Sven Eckelmann   batman-adv: Move ...
473
474
475
  
  	return ret;
  }
3dbd550b8   Sven Eckelmann   batman-adv: Allow...
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
  /**
   * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface
   * @dev: batadv_soft_interface used as master interface
   * @slave_dev: net_device which should become the slave interface
   *
   * Return 0 if successful or error otherwise.
   */
  static int batadv_softif_slave_add(struct net_device *dev,
  				   struct net_device *slave_dev)
  {
  	struct batadv_hard_iface *hard_iface;
  	int ret = -EINVAL;
  
  	hard_iface = batadv_hardif_get_by_netdev(slave_dev);
  	if (!hard_iface || hard_iface->soft_iface != NULL)
  		goto out;
  
  	ret = batadv_hardif_enable_interface(hard_iface, dev->name);
  
  out:
  	if (hard_iface)
  		batadv_hardif_free_ref(hard_iface);
  	return ret;
  }
  
  /**
   * batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface
   * @dev: batadv_soft_interface used as master interface
   * @slave_dev: net_device which should be removed from the master interface
   *
   * Return 0 if successful or error otherwise.
   */
  static int batadv_softif_slave_del(struct net_device *dev,
  				   struct net_device *slave_dev)
  {
  	struct batadv_hard_iface *hard_iface;
  	int ret = -EINVAL;
  
  	hard_iface = batadv_hardif_get_by_netdev(slave_dev);
  
  	if (!hard_iface || hard_iface->soft_iface != dev)
  		goto out;
  
  	batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP);
  	ret = 0;
  
  out:
  	if (hard_iface)
  		batadv_hardif_free_ref(hard_iface);
  	return ret;
  }
37130293f   Sven Eckelmann   batman-adv: Move ...
527
528
529
530
531
532
533
534
  static const struct net_device_ops batadv_netdev_ops = {
  	.ndo_init = batadv_softif_init_late,
  	.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,
3dbd550b8   Sven Eckelmann   batman-adv: Allow...
535
536
537
  	.ndo_validate_addr = eth_validate_addr,
  	.ndo_add_slave = batadv_softif_slave_add,
  	.ndo_del_slave = batadv_softif_slave_del,
37130293f   Sven Eckelmann   batman-adv: Move ...
538
539
540
  };
  
  /**
b3246020e   Sven Eckelmann   batman-adv: Move ...
541
542
543
544
545
546
547
   * batadv_softif_free - Deconstructor of batadv_soft_interface
   * @dev: Device to cleanup and remove
   */
  static void batadv_softif_free(struct net_device *dev)
  {
  	batadv_debugfs_del_meshif(dev);
  	batadv_mesh_free(dev);
0c501345c   Antonio Quartulli   batman-adv: fix g...
548
549
550
551
552
553
  
  	/* some scheduled RCU callbacks need the bat_priv struct to accomplish
  	 * their tasks. Wait for them all to be finished before freeing the
  	 * netdev and its private data (bat_priv)
  	 */
  	rcu_barrier();
b3246020e   Sven Eckelmann   batman-adv: Move ...
554
555
556
557
  	free_netdev(dev);
  }
  
  /**
37130293f   Sven Eckelmann   batman-adv: Move ...
558
559
560
561
562
563
564
565
566
567
   * batadv_softif_init_early - early stage initialization of soft interface
   * @dev: registered network device to modify
   */
  static void batadv_softif_init_early(struct net_device *dev)
  {
  	struct batadv_priv *priv = netdev_priv(dev);
  
  	ether_setup(dev);
  
  	dev->netdev_ops = &batadv_netdev_ops;
b3246020e   Sven Eckelmann   batman-adv: Move ...
568
  	dev->destructor = batadv_softif_free;
37130293f   Sven Eckelmann   batman-adv: Move ...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  	dev->tx_queue_len = 0;
  
  	/* can't call min_mtu, because the needed variables
  	 * have not been initialized yet
  	 */
  	dev->mtu = ETH_DATA_LEN;
  	/* reserve more space in the skbuff for our header */
  	dev->hard_header_len = BATADV_HEADER_LEN;
  
  	/* generate random address */
  	eth_hw_addr_random(dev);
  
  	SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
  
  	memset(priv, 0, sizeof(*priv));
  }
  
  struct net_device *batadv_softif_create(const char *name)
  {
  	struct net_device *soft_iface;
  	int ret;
  
  	soft_iface = alloc_netdev(sizeof(struct batadv_priv), name,
  				  batadv_softif_init_early);
  	if (!soft_iface)
  		return NULL;
a4ac28c0d   Sven Eckelmann   batman-adv: Allow...
595
  	soft_iface->rtnl_link_ops = &batadv_link_ops;
37130293f   Sven Eckelmann   batman-adv: Move ...
596
597
598
599
600
601
602
603
604
605
  	ret = register_netdevice(soft_iface);
  	if (ret < 0) {
  		pr_err("Unable to register the batman interface '%s': %i
  ",
  		       name, ret);
  		free_netdev(soft_iface);
  		return NULL;
  	}
  
  	return soft_iface;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
606
  }
e07932ae6   Marek Lindner   batman-adv: renam...
607
608
609
610
611
  /**
   * batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs
   * @soft_iface: the to-be-removed batman-adv interface
   */
  void batadv_softif_destroy_sysfs(struct net_device *soft_iface)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
612
  {
5bc44dc84   Simon Wunderlich   batman-adv: postp...
613
  	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
5bc44dc84   Simon Wunderlich   batman-adv: postp...
614
  	queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
615
  }
a4ac28c0d   Sven Eckelmann   batman-adv: Allow...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
  /**
   * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink
   * @soft_iface: the to-be-removed batman-adv interface
   * @head: list pointer
   */
  static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
  					  struct list_head *head)
  {
  	struct batadv_hard_iface *hard_iface;
  
  	list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
  		if (hard_iface->soft_iface == soft_iface)
  			batadv_hardif_disable_interface(hard_iface,
  							BATADV_IF_CLEANUP_KEEP);
  	}
  
  	batadv_sysfs_del_meshif(soft_iface);
  	unregister_netdevice_queue(soft_iface, head);
  }
04b482a21   Sven Eckelmann   batman-adv: Prefi...
635
  int batadv_softif_is_valid(const struct net_device *net_dev)
e44d8fe2b   Sven Eckelmann   batman-adv: Disal...
636
  {
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
637
  	if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx)
e44d8fe2b   Sven Eckelmann   batman-adv: Disal...
638
  		return 1;
e44d8fe2b   Sven Eckelmann   batman-adv: Disal...
639
640
641
  
  	return 0;
  }
a4ac28c0d   Sven Eckelmann   batman-adv: Allow...
642
643
644
645
646
647
  struct rtnl_link_ops batadv_link_ops __read_mostly = {
  	.kind		= "batadv",
  	.priv_size	= sizeof(struct batadv_priv),
  	.setup		= batadv_softif_init_early,
  	.dellink	= batadv_softif_destroy_netlink,
  };
c6c8fea29   Sven Eckelmann   net: Add batman-a...
648
  /* ethtool */
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
649
  static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
650
651
652
  {
  	cmd->supported = 0;
  	cmd->advertising = 0;
707394972   David Decotigny   ethtool: cosmetic...
653
  	ethtool_cmd_speed_set(cmd, SPEED_10);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
654
655
656
657
658
659
660
661
662
663
  	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;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
664
665
  static void batadv_get_drvinfo(struct net_device *dev,
  			       struct ethtool_drvinfo *info)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
666
  {
7826d43f2   Jiri Pirko   ethtool: fix drvi...
667
668
669
670
  	strlcpy(info->driver, "B.A.T.M.A.N. advanced", sizeof(info->driver));
  	strlcpy(info->version, BATADV_SOURCE_VERSION, sizeof(info->version));
  	strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
  	strlcpy(info->bus_info, "batman", sizeof(info->bus_info));
c6c8fea29   Sven Eckelmann   net: Add batman-a...
671
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
672
  static u32 batadv_get_msglevel(struct net_device *dev)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
673
674
675
  {
  	return -EOPNOTSUPP;
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
676
  static void batadv_set_msglevel(struct net_device *dev, u32 value)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
677
678
  {
  }
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
679
  static u32 batadv_get_link(struct net_device *dev)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
680
681
682
  {
  	return 1;
  }
f8214865a   Martin Hundebøll   batman-adv: Add g...
683
684
685
686
687
688
689
  
  /* 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];
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
690
  } batadv_counters_strings[] = {
1c9b0550f   Marek Lindner   batman-adv: conve...
691
692
693
694
695
  	{ "tx" },
  	{ "tx_bytes" },
  	{ "tx_dropped" },
  	{ "rx" },
  	{ "rx_bytes" },
f8214865a   Martin Hundebøll   batman-adv: Add g...
696
697
698
699
700
701
702
703
704
705
706
707
  	{ "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" },
4046b24af   Martin Hundebøll   batman-adv: Add g...
708
709
710
711
712
713
714
  #ifdef CONFIG_BATMAN_ADV_DAT
  	{ "dat_get_tx" },
  	{ "dat_get_rx" },
  	{ "dat_put_tx" },
  	{ "dat_put_rx" },
  	{ "dat_cached_reply_tx" },
  #endif
3c12de9a5   Martin Hundebøll   batman-adv: netwo...
715
716
717
718
719
  #ifdef CONFIG_BATMAN_ADV_NC
  	{ "nc_code" },
  	{ "nc_code_bytes" },
  	{ "nc_recode" },
  	{ "nc_recode_bytes" },
612d2b4fe   Martin Hundebøll   batman-adv: netwo...
720
  	{ "nc_buffer" },
2df5278b0   Martin Hundebøll   batman-adv: netwo...
721
722
723
724
  	{ "nc_decode" },
  	{ "nc_decode_bytes" },
  	{ "nc_decode_failed" },
  	{ "nc_sniffed" },
3c12de9a5   Martin Hundebøll   batman-adv: netwo...
725
  #endif
f8214865a   Martin Hundebøll   batman-adv: Add g...
726
727
728
729
730
731
  };
  
  static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
  			       uint8_t *data)
  {
  	if (stringset == ETH_SS_STATS)
0294ca0d9   Sven Eckelmann   batman-adv: Prefi...
732
733
  		memcpy(data, batadv_counters_strings,
  		       sizeof(batadv_counters_strings));
f8214865a   Martin Hundebøll   batman-adv: Add g...
734
735
736
737
738
739
  }
  
  static void batadv_get_ethtool_stats(struct net_device *dev,
  				     struct ethtool_stats *stats,
  				     uint64_t *data)
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
740
  	struct batadv_priv *bat_priv = netdev_priv(dev);
f8214865a   Martin Hundebøll   batman-adv: Add g...
741
  	int i;
d69909d2f   Sven Eckelmann   batman-adv: Prefi...
742
  	for (i = 0; i < BATADV_CNT_NUM; i++)
f8214865a   Martin Hundebøll   batman-adv: Add g...
743
744
745
746
747
748
  		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)
d69909d2f   Sven Eckelmann   batman-adv: Prefi...
749
  		return BATADV_CNT_NUM;
f8214865a   Martin Hundebøll   batman-adv: Add g...
750
751
752
  
  	return -EOPNOTSUPP;
  }