soft-interface.c 11.4 KB
Newer Older
1
/*
2
 * Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * 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"
#include "routing.h"
#include "send.h"
#include "bat_debugfs.h"
#include "translation-table.h"
#include "hash.h"
#include "gateway_common.h"
#include "gateway_client.h"
#include "bat_sysfs.h"
33
#include "originator.h"
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include "unicast.h"


static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
static void bat_get_drvinfo(struct net_device *dev,
			    struct ethtool_drvinfo *info);
static u32 bat_get_msglevel(struct net_device *dev);
static void bat_set_msglevel(struct net_device *dev, u32 value);
static u32 bat_get_link(struct net_device *dev);

static const struct ethtool_ops bat_ethtool_ops = {
	.get_settings = bat_get_settings,
	.get_drvinfo = bat_get_drvinfo,
	.get_msglevel = bat_get_msglevel,
	.set_msglevel = bat_set_msglevel,
	.get_link = bat_get_link,
};

int my_skb_head_push(struct sk_buff *skb, unsigned int len)
{
	int result;

	/**
	 * TODO: We must check if we can release all references to non-payload
	 * 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;
}

static int interface_open(struct net_device *dev)
{
	netif_start_queue(dev);
	return 0;
}

static int interface_release(struct net_device *dev)
{
	netif_stop_queue(dev);
	return 0;
}

static struct net_device_stats *interface_stats(struct net_device *dev)
{
	struct bat_priv *bat_priv = netdev_priv(dev);
	return &bat_priv->stats;
}

static int interface_set_mac_addr(struct net_device *dev, void *p)
{
	struct bat_priv *bat_priv = netdev_priv(dev);
	struct sockaddr *addr = p;

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

102
	/* only modify transtable if it has been initialized before */
103
	if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
104
		tt_local_remove(bat_priv, dev->dev_addr,
105
				"mac address changed", false);
106
		tt_local_add(dev, addr->sa_data, NULL_IFINDEX);
107 108 109
	}

	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
110
	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
111 112 113 114 115 116 117 118 119 120 121 122 123 124
	return 0;
}

static int interface_change_mtu(struct net_device *dev, int new_mtu)
{
	/* check ranges */
	if ((new_mtu < 68) || (new_mtu > hardif_min_mtu(dev)))
		return -EINVAL;

	dev->mtu = new_mtu;

	return 0;
}

125
static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
126 127 128
{
	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
	struct bat_priv *bat_priv = netdev_priv(soft_iface);
129
	struct hard_iface *primary_if = NULL;
130 131
	struct bcast_packet *bcast_packet;
	struct vlan_ethhdr *vhdr;
132
	unsigned int header_len = 0;
133 134
	int data_len = skb->len, ret;
	short vid = -1;
135
	bool do_bcast = false;
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
		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;

		if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
			break;

		/* fall through */
	case ETH_P_BATMAN:
		goto dropped;
153
	}
154

155
	/* Register the client MAC in the transtable */
156
	tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
157

158 159
	if (is_multicast_ether_addr(ethhdr->h_dest)) {
		do_bcast = true;
160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
		switch (atomic_read(&bat_priv->gw_mode)) {
		case GW_MODE_SERVER:
			/* gateway servers should not send dhcp
			 * requests into the mesh */
			ret = gw_is_dhcp_target(skb, &header_len);
			if (ret)
				goto dropped;
			break;
		case GW_MODE_CLIENT:
			/* gateway clients should send dhcp requests
			 * via unicast to their gateway */
			ret = gw_is_dhcp_target(skb, &header_len);
			if (ret)
				do_bcast = false;
			break;
		case GW_MODE_OFF:
		default:
			break;
		}
180 181 182 183
	}

	/* ethernet packet should be broadcasted */
	if (do_bcast) {
184 185
		primary_if = primary_if_get_selected(bat_priv);
		if (!primary_if)
186 187
			goto dropped;

188
		if (my_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
189 190 191
			goto dropped;

		bcast_packet = (struct bcast_packet *)skb->data;
192 193
		bcast_packet->header.version = COMPAT_VERSION;
		bcast_packet->header.ttl = TTL;
194 195

		/* batman packet type: broadcast */
196
		bcast_packet->header.packet_type = BAT_BCAST;
197 198 199 200

		/* hw address of first interface is the orig mac because only
		 * this mac is known throughout the mesh */
		memcpy(bcast_packet->orig,
201
		       primary_if->net_dev->dev_addr, ETH_ALEN);
202 203 204 205 206

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

207
		add_bcast_packet_to_list(bat_priv, skb, 1);
208 209 210 211 212 213 214

		/* a copy is stored in the bcast list, therefore removing
		 * the original skb. */
		kfree_skb(skb);

	/* unicast packet */
	} else {
215 216 217 218 219 220
		if (atomic_read(&bat_priv->gw_mode) != GW_MODE_OFF) {
			ret = gw_out_of_range(bat_priv, skb, ethhdr);
			if (ret)
				goto dropped;
		}

221 222 223 224 225 226 227 228 229 230 231 232 233 234
		ret = unicast_send_skb(skb, bat_priv);
		if (ret != 0)
			goto dropped_freed;
	}

	bat_priv->stats.tx_packets++;
	bat_priv->stats.tx_bytes += data_len;
	goto end;

dropped:
	kfree_skb(skb);
dropped_freed:
	bat_priv->stats.tx_dropped++;
end:
235 236
	if (primary_if)
		hardif_free_ref(primary_if);
237 238 239 240
	return NETDEV_TX_OK;
}

void interface_rx(struct net_device *soft_iface,
241
		  struct sk_buff *skb, struct hard_iface *recv_if,
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
		  int hdr_size)
{
	struct bat_priv *bat_priv = netdev_priv(soft_iface);
	struct ethhdr *ethhdr;
	struct vlan_ethhdr *vhdr;
	short vid = -1;

	/* 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;

		if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
			break;

		/* fall through */
	case ETH_P_BATMAN:
		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 已提交
276
	/* should not be necessary anymore as we use skb_pull_rcsum()
277 278 279 280 281 282 283 284 285 286
	 * TODO: please verify this and remove this TODO
	 * -- Dec 21st 2009, Simon Wunderlich */

/*	skb->ip_summed = CHECKSUM_UNNECESSARY;*/

	bat_priv->stats.rx_packets++;
	bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);

	soft_iface->last_rx = jiffies;

287 288 289
	if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
		goto dropped;

290
	netif_rx(skb);
291
	goto out;
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316

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

static const struct net_device_ops bat_netdev_ops = {
	.ndo_open = interface_open,
	.ndo_stop = interface_release,
	.ndo_get_stats = interface_stats,
	.ndo_set_mac_address = interface_set_mac_addr,
	.ndo_change_mtu = interface_change_mtu,
	.ndo_start_xmit = interface_tx,
	.ndo_validate_addr = eth_validate_addr
};

static void interface_setup(struct net_device *dev)
{
	struct bat_priv *priv = netdev_priv(dev);

	ether_setup(dev);

	dev->netdev_ops = &bat_netdev_ops;
	dev->destructor = free_netdev;
317
	dev->tx_queue_len = 0;
318 319 320 321 322 323

	/**
	 * can't call min_mtu, because the needed variables
	 * have not been initialized yet
	 */
	dev->mtu = ETH_DATA_LEN;
324 325
	/* reserve more space in the skbuff for our header */
	dev->hard_header_len = BAT_HEADER_LEN;
326 327

	/* generate random address */
328
	eth_hw_addr_random(dev);
329 330 331

	SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);

332
	memset(priv, 0, sizeof(*priv));
333 334
}

335
struct net_device *softif_create(const char *name)
336 337 338 339 340
{
	struct net_device *soft_iface;
	struct bat_priv *bat_priv;
	int ret;

341
	soft_iface = alloc_netdev(sizeof(*bat_priv), name, interface_setup);
342

343
	if (!soft_iface)
344 345
		goto out;

346
	ret = register_netdevice(soft_iface);
347 348 349 350 351 352 353 354 355 356
	if (ret < 0) {
		pr_err("Unable to register the batman interface '%s': %i\n",
		       name, ret);
		goto free_soft_iface;
	}

	bat_priv = netdev_priv(soft_iface);

	atomic_set(&bat_priv->aggregated_ogms, 1);
	atomic_set(&bat_priv->bonding, 0);
357
	atomic_set(&bat_priv->ap_isolation, 0);
358 359 360 361 362
	atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
	atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
	atomic_set(&bat_priv->gw_sel_class, 20);
	atomic_set(&bat_priv->gw_bandwidth, 41);
	atomic_set(&bat_priv->orig_interval, 1000);
363
	atomic_set(&bat_priv->hop_penalty, 30);
364 365 366 367 368 369 370
	atomic_set(&bat_priv->log_level, 0);
	atomic_set(&bat_priv->fragmentation, 1);
	atomic_set(&bat_priv->bcast_queue_left, BCAST_QUEUE_LEN);
	atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);

	atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
	atomic_set(&bat_priv->bcast_seqno, 1);
371 372 373 374 375 376
	atomic_set(&bat_priv->ttvn, 0);
	atomic_set(&bat_priv->tt_local_changes, 0);
	atomic_set(&bat_priv->tt_ogm_append_cnt, 0);

	bat_priv->tt_buff = NULL;
	bat_priv->tt_buff_len = 0;
377
	bat_priv->tt_poss_change = false;
378 379 380 381

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

382 383 384 385
	ret = bat_algo_select(bat_priv, bat_routing_algo);
	if (ret < 0)
		goto unreg_soft_iface;

386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
	ret = sysfs_add_meshif(soft_iface);
	if (ret < 0)
		goto unreg_soft_iface;

	ret = debugfs_add_meshif(soft_iface);
	if (ret < 0)
		goto unreg_sysfs;

	ret = mesh_init(soft_iface);
	if (ret < 0)
		goto unreg_debugfs;

	return soft_iface;

unreg_debugfs:
	debugfs_del_meshif(soft_iface);
unreg_sysfs:
	sysfs_del_meshif(soft_iface);
unreg_soft_iface:
405
	unregister_netdevice(soft_iface);
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
	return NULL;

free_soft_iface:
	free_netdev(soft_iface);
out:
	return NULL;
}

void softif_destroy(struct net_device *soft_iface)
{
	debugfs_del_meshif(soft_iface);
	sysfs_del_meshif(soft_iface);
	mesh_free(soft_iface);
	unregister_netdevice(soft_iface);
}

422
int softif_is_valid(const struct net_device *net_dev)
423 424 425 426 427 428 429
{
	if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
		return 1;

	return 0;
}

430 431 432 433 434
/* ethtool */
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
	cmd->supported = 0;
	cmd->advertising = 0;
435
	ethtool_cmd_speed_set(cmd, SPEED_10);
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
	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;
}

static void bat_get_drvinfo(struct net_device *dev,
			    struct ethtool_drvinfo *info)
{
	strcpy(info->driver, "B.A.T.M.A.N. advanced");
	strcpy(info->version, SOURCE_VERSION);
	strcpy(info->fw_version, "N/A");
	strcpy(info->bus_info, "batman");
}

static u32 bat_get_msglevel(struct net_device *dev)
{
	return -EOPNOTSUPP;
}

static void bat_set_msglevel(struct net_device *dev, u32 value)
{
}

static u32 bat_get_link(struct net_device *dev)
{
	return 1;
}