lec.c 60.5 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 * lec.c: Lan Emulation driver
Linus Torvalds's avatar
Linus Torvalds committed
3
 *
4
 * Marko Kiiskila <mkiiskila@yahoo.com>
Linus Torvalds's avatar
Linus Torvalds committed
5 6
 */

7 8
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__

9
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
10 11
#include <linux/kernel.h>
#include <linux/bitops.h>
12
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
13 14 15 16 17 18 19 20 21

/* We are ethernet device */
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <net/sock.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <asm/byteorder.h>
22
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36
#include <net/arp.h>
#include <net/dst.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/seq_file.h>

/* And atm device */
#include <linux/atmdev.h>
#include <linux/atmlec.h>

/* Proxy LEC knows about bridging */
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include "../bridge/br_private.h"

37
static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
Linus Torvalds's avatar
Linus Torvalds committed
38 39 40 41 42 43 44 45 46 47
#endif

/* Modular too */
#include <linux/module.h>
#include <linux/init.h>

#include "lec.h"
#include "lec_arpc.h"
#include "resources.h"

48 49 50 51 52
#define DUMP_PACKETS 0		/*
				 * 0 = None,
				 * 1 = 30 first bytes
				 * 2 = Whole packet
				 */
Linus Torvalds's avatar
Linus Torvalds committed
53

54 55 56 57
#define LEC_UNRES_QUE_LEN 8	/*
				 * number of tx packets to queue for a
				 * single destination while waiting for SVC
				 */
Linus Torvalds's avatar
Linus Torvalds committed
58 59

static int lec_open(struct net_device *dev);
60 61
static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
				  struct net_device *dev);
Linus Torvalds's avatar
Linus Torvalds committed
62
static int lec_close(struct net_device *dev);
63
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
64
					  const unsigned char *mac_addr);
Linus Torvalds's avatar
Linus Torvalds committed
65
static int lec_arp_remove(struct lec_priv *priv,
66
			  struct lec_arp_table *to_remove);
Linus Torvalds's avatar
Linus Torvalds committed
67
/* LANE2 functions */
68 69 70
static void lane2_associate_ind(struct net_device *dev, const u8 *mac_address,
				const u8 *tlvs, u32 sizeoftlvs);
static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
71
			 u8 **tlvs, u32 *sizeoftlvs);
72 73
static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
			       const u8 *tlvs, u32 sizeoftlvs);
Linus Torvalds's avatar
Linus Torvalds committed
74

75
static int lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr,
Linus Torvalds's avatar
Linus Torvalds committed
76 77 78 79 80
			   unsigned long permanent);
static void lec_arp_check_empties(struct lec_priv *priv,
				  struct atm_vcc *vcc, struct sk_buff *skb);
static void lec_arp_destroy(struct lec_priv *priv);
static void lec_arp_init(struct lec_priv *priv);
81
static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
82
				       const unsigned char *mac_to_find,
Linus Torvalds's avatar
Linus Torvalds committed
83 84
				       int is_rdesc,
				       struct lec_arp_table **ret_entry);
85
static void lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
86 87
			   const unsigned char *atm_addr,
			   unsigned long remoteflag,
Linus Torvalds's avatar
Linus Torvalds committed
88 89 90 91
			   unsigned int targetless_le_arp);
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
static void lec_set_flush_tran_id(struct lec_priv *priv,
92
				  const unsigned char *atm_addr,
Linus Torvalds's avatar
Linus Torvalds committed
93
				  unsigned long tran_id);
94 95
static void lec_vcc_added(struct lec_priv *priv,
			  const struct atmlec_ioc *ioc_data,
Linus Torvalds's avatar
Linus Torvalds committed
96
			  struct atm_vcc *vcc,
97 98
			  void (*old_push)(struct atm_vcc *vcc,
					   struct sk_buff *skb));
Linus Torvalds's avatar
Linus Torvalds committed
99 100
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);

101 102 103 104 105 106 107 108 109 110 111 112
/* must be done under lec_arp_lock */
static inline void lec_arp_hold(struct lec_arp_table *entry)
{
	atomic_inc(&entry->usage);
}

static inline void lec_arp_put(struct lec_arp_table *entry)
{
	if (atomic_dec_and_test(&entry->usage))
		kfree(entry);
}

Linus Torvalds's avatar
Linus Torvalds committed
113
static struct lane2_ops lane2_ops = {
114 115 116
	lane2_resolve,		/* resolve,             spec 3.1.3 */
	lane2_associate_req,	/* associate_req,       spec 3.1.4 */
	NULL			/* associate indicator, spec 3.1.5 */
Linus Torvalds's avatar
Linus Torvalds committed
117 118
};

119
static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
Linus Torvalds's avatar
Linus Torvalds committed
120 121 122 123 124 125 126

/* Device structures */
static struct net_device *dev_lec[MAX_LEC_ITF];

#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
{
127 128 129 130 131 132 133 134 135 136
	char *buff;
	struct lec_priv *priv;

	/*
	 * Check if this is a BPDU. If so, ask zeppelin to send
	 * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
	 * as the Config BPDU has
	 */
	buff = skb->data + skb->dev->hard_header_len;
	if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
Linus Torvalds's avatar
Linus Torvalds committed
137
		struct sock *sk;
138 139 140 141 142 143 144 145 146 147
		struct sk_buff *skb2;
		struct atmlec_msg *mesg;

		skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
		if (skb2 == NULL)
			return;
		skb2->len = sizeof(struct atmlec_msg);
		mesg = (struct atmlec_msg *)skb2->data;
		mesg->type = l_topology_change;
		buff += 4;
148 149
		mesg->content.normal.flag = *buff & 0x01;
					/* 0x01 is topology change */
150

151
		priv = netdev_priv(dev);
152
		atm_force_charge(priv->lecd, skb2->truesize);
Linus Torvalds's avatar
Linus Torvalds committed
153
		sk = sk_atm(priv->lecd);
154 155 156
		skb_queue_tail(&sk->sk_receive_queue, skb2);
		sk->sk_data_ready(sk, skb2->len);
	}
Linus Torvalds's avatar
Linus Torvalds committed
157 158 159 160 161 162 163 164 165 166 167 168
}
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */

/*
 * Open/initialize the netdevice. This is called (in the current kernel)
 * sometime after booting when the 'ifconfig' program is run.
 *
 * This routine should set everything up anew at each open, even
 * registers that "should" only need to be set once at boot, so that
 * there is non-reboot way to recover if something goes wrong.
 */

169
static int lec_open(struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
170 171
{
	netif_start_queue(dev);
172 173

	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
174 175
}

176 177
static void
lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
178
{
179 180
	struct net_device *dev = skb->dev;

Linus Torvalds's avatar
Linus Torvalds committed
181 182 183 184 185
	ATM_SKB(skb)->vcc = vcc;
	ATM_SKB(skb)->atm_options = vcc->atm_options;

	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
	if (vcc->send(vcc, skb) < 0) {
186
		dev->stats.tx_dropped++;
Linus Torvalds's avatar
Linus Torvalds committed
187 188 189
		return;
	}

190 191
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;
Linus Torvalds's avatar
Linus Torvalds committed
192 193
}

194
static void lec_tx_timeout(struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
195
{
196
	pr_info("%s\n", dev->name);
Linus Torvalds's avatar
Linus Torvalds committed
197 198 199 200
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}

201 202
static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
				  struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
203
{
204
	struct sk_buff *skb2;
205
	struct lec_priv *priv = netdev_priv(dev);
206 207
	struct lecdatahdr_8023 *lec_h;
	struct atm_vcc *vcc;
Linus Torvalds's avatar
Linus Torvalds committed
208
	struct lec_arp_table *entry;
209
	unsigned char *dst;
Linus Torvalds's avatar
Linus Torvalds committed
210
	int min_frame_size;
211 212
	int is_rdesc;

213
	pr_debug("called\n");
214
	if (!priv->lecd) {
215
		pr_info("%s:No lecd attached\n", dev->name);
216
		dev->stats.tx_errors++;
217
		netif_stop_queue(dev);
218 219
		kfree_skb(skb);
		return NETDEV_TX_OK;
220 221
	}

222
	pr_debug("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
223 224
		 (long)skb->head, (long)skb->data, (long)skb_tail_pointer(skb),
		 (long)skb_end_pointer(skb));
Linus Torvalds's avatar
Linus Torvalds committed
225
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
226 227
	if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
		lec_handle_bridge(skb, dev);
Linus Torvalds's avatar
Linus Torvalds committed
228 229
#endif

230 231
	/* Make sure we have room for lec_id */
	if (skb_headroom(skb) < 2) {
232
		pr_debug("reallocating skb\n");
233 234 235
		skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
		kfree_skb(skb);
		if (skb2 == NULL)
236
			return NETDEV_TX_OK;
237 238 239
		skb = skb2;
	}
	skb_push(skb, 2);
Linus Torvalds's avatar
Linus Torvalds committed
240

241
	/* Put le header to place */
242 243
	lec_h = (struct lecdatahdr_8023 *)skb->data;
	lec_h->le_header = htons(priv->lecid);
Linus Torvalds's avatar
Linus Torvalds committed
244 245

#if DUMP_PACKETS >= 2
246
#define MAX_DUMP_SKB 99
Linus Torvalds's avatar
Linus Torvalds committed
247
#elif DUMP_PACKETS >= 1
248 249 250 251 252 253 254
#define MAX_DUMP_SKB 30
#endif
#if DUMP_PACKETS >= 1
	printk(KERN_DEBUG "%s: send datalen:%ld lecid:%4.4x\n",
	       dev->name, skb->len, priv->lecid);
	print_hex_dump(KERN_DEBUG, "", DUMP_OFFSET, 16, 1,
		       skb->data, min(skb->len, MAX_DUMP_SKB), true);
Linus Torvalds's avatar
Linus Torvalds committed
255 256
#endif /* DUMP_PACKETS >= 1 */

257
	/* Minimum ethernet-frame size */
258
	min_frame_size = LEC_MINIMUM_8023_SIZE;
259 260 261 262 263 264 265
	if (skb->len < min_frame_size) {
		if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
			skb2 = skb_copy_expand(skb, 0,
					       min_frame_size - skb->truesize,
					       GFP_ATOMIC);
			dev_kfree_skb(skb);
			if (skb2 == NULL) {
266
				dev->stats.tx_dropped++;
267
				return NETDEV_TX_OK;
268 269 270
			}
			skb = skb2;
		}
Linus Torvalds's avatar
Linus Torvalds committed
271
		skb_put(skb, min_frame_size - skb->len);
272 273 274 275 276 277 278
	}

	/* Send to right vcc */
	is_rdesc = 0;
	dst = lec_h->h_dest;
	entry = NULL;
	vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
279 280
	pr_debug("%s:vcc:%p vcc_flags:%lx, entry:%p\n",
		 dev->name, vcc, vcc ? vcc->flags : 0, entry);
281 282
	if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) {
		if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
283 284
			pr_debug("%s:queuing packet, MAC address %pM\n",
				 dev->name, lec_h->h_dest);
285 286
			skb_queue_tail(&entry->tx_wait, skb);
		} else {
287 288
			pr_debug("%s:tx queue full or no arp entry, dropping, MAC address: %pM\n",
				 dev->name, lec_h->h_dest);
289
			dev->stats.tx_dropped++;
290 291
			dev_kfree_skb(skb);
		}
292
		goto out;
293 294
	}
#if DUMP_PACKETS > 0
295 296
	printk(KERN_DEBUG "%s:sending to vpi:%d vci:%d\n",
	       dev->name, vcc->vpi, vcc->vci);
Linus Torvalds's avatar
Linus Torvalds committed
297
#endif /* DUMP_PACKETS > 0 */
298 299

	while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
300
		pr_debug("emptying tx queue, MAC address %pM\n", lec_h->h_dest);
301
		lec_send(vcc, skb2);
302
	}
Linus Torvalds's avatar
Linus Torvalds committed
303

304
	lec_send(vcc, skb);
Linus Torvalds's avatar
Linus Torvalds committed
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

	if (!atm_may_send(vcc, 0)) {
		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);

		vpriv->xoff = 1;
		netif_stop_queue(dev);

		/*
		 * vcc->pop() might have occurred in between, making
		 * the vcc usuable again.  Since xmit is serialized,
		 * this is the only situation we have to re-test.
		 */

		if (atm_may_send(vcc, 0))
			netif_wake_queue(dev);
	}

322 323 324
out:
	if (entry)
		lec_arp_put(entry);
Linus Torvalds's avatar
Linus Torvalds committed
325
	dev->trans_start = jiffies;
326
	return NETDEV_TX_OK;
Linus Torvalds's avatar
Linus Torvalds committed
327 328 329
}

/* The inverse routine to net_open(). */
330
static int lec_close(struct net_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
331
{
332 333
	netif_stop_queue(dev);
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
334 335
}

336
static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
337 338
{
	unsigned long flags;
339
	struct net_device *dev = (struct net_device *)vcc->proto_data;
340
	struct lec_priv *priv = netdev_priv(dev);
341 342 343 344
	struct atmlec_msg *mesg;
	struct lec_arp_table *entry;
	int i;
	char *tmp;		/* FIXME */
Linus Torvalds's avatar
Linus Torvalds committed
345 346

	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
347 348 349
	mesg = (struct atmlec_msg *)skb->data;
	tmp = skb->data;
	tmp += sizeof(struct atmlec_msg);
350
	pr_debug("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
351 352
	switch (mesg->type) {
	case l_set_mac_addr:
353
		for (i = 0; i < 6; i++)
354 355 356
			dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
		break;
	case l_del_mac_addr:
357
		for (i = 0; i < 6; i++)
358 359 360 361 362 363 364 365 366 367 368 369 370
			dev->dev_addr[i] = 0;
		break;
	case l_addr_delete:
		lec_addr_delete(priv, mesg->content.normal.atm_addr,
				mesg->content.normal.flag);
		break;
	case l_topology_change:
		priv->topology_change = mesg->content.normal.flag;
		break;
	case l_flush_complete:
		lec_flush_complete(priv, mesg->content.normal.flag);
		break;
	case l_narp_req:	/* LANE2: see 7.1.35 in the lane2 spec */
Linus Torvalds's avatar
Linus Torvalds committed
371
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
372 373
		entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
		lec_arp_remove(priv, entry);
Linus Torvalds's avatar
Linus Torvalds committed
374 375
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

376 377 378 379 380 381 382 383
		if (mesg->content.normal.no_source_le_narp)
			break;
		/* FALL THROUGH */
	case l_arp_update:
		lec_arp_update(priv, mesg->content.normal.mac_addr,
			       mesg->content.normal.atm_addr,
			       mesg->content.normal.flag,
			       mesg->content.normal.targetless_le_arp);
384
		pr_debug("in l_arp_update\n");
385
		if (mesg->sizeoftlvs != 0) {	/* LANE2 3.1.5 */
386 387
			pr_debug("LANE2 3.1.5, got tlvs, size %d\n",
				 mesg->sizeoftlvs);
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
			lane2_associate_ind(dev, mesg->content.normal.mac_addr,
					    tmp, mesg->sizeoftlvs);
		}
		break;
	case l_config:
		priv->maximum_unknown_frame_count =
		    mesg->content.config.maximum_unknown_frame_count;
		priv->max_unknown_frame_time =
		    (mesg->content.config.max_unknown_frame_time * HZ);
		priv->max_retry_count = mesg->content.config.max_retry_count;
		priv->aging_time = (mesg->content.config.aging_time * HZ);
		priv->forward_delay_time =
		    (mesg->content.config.forward_delay_time * HZ);
		priv->arp_response_time =
		    (mesg->content.config.arp_response_time * HZ);
		priv->flush_timeout = (mesg->content.config.flush_timeout * HZ);
		priv->path_switching_delay =
		    (mesg->content.config.path_switching_delay * HZ);
406 407
		priv->lane_version = mesg->content.config.lane_version;
					/* LANE2 */
Linus Torvalds's avatar
Linus Torvalds committed
408 409 410
		priv->lane2_ops = NULL;
		if (priv->lane_version > 1)
			priv->lane2_ops = &lane2_ops;
411
		if (dev_set_mtu(dev, mesg->content.config.mtu))
412 413
			pr_info("%s: change_mtu to %d failed\n",
				dev->name, mesg->content.config.mtu);
Linus Torvalds's avatar
Linus Torvalds committed
414
		priv->is_proxy = mesg->content.config.is_proxy;
415 416 417 418 419 420 421 422 423 424
		break;
	case l_flush_tran_id:
		lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
				      mesg->content.normal.flag);
		break;
	case l_set_lecid:
		priv->lecid =
		    (unsigned short)(0xffff & mesg->content.normal.flag);
		break;
	case l_should_bridge:
Linus Torvalds's avatar
Linus Torvalds committed
425
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
426 427 428
	{
		pr_debug("%s: bridge zeppelin asks about %pM\n",
			 dev->name, mesg->content.proxy.mac_addr);
429

430 431
		if (br_fdb_test_addr_hook == NULL)
			break;
432

433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
		if (br_fdb_test_addr_hook(dev, mesg->content.proxy.mac_addr)) {
			/* hit from bridge table, send LE_ARP_RESPONSE */
			struct sk_buff *skb2;
			struct sock *sk;

			pr_debug("%s: entry found, responding to zeppelin\n",
				 dev->name);
			skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
			if (skb2 == NULL)
				break;
			skb2->len = sizeof(struct atmlec_msg);
			skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg));
			atm_force_charge(priv->lecd, skb2->truesize);
			sk = sk_atm(priv->lecd);
			skb_queue_tail(&sk->sk_receive_queue, skb2);
			sk->sk_data_ready(sk, skb2->len);
449
		}
450
	}
Linus Torvalds's avatar
Linus Torvalds committed
451
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
452 453
		break;
	default:
454
		pr_info("%s: Unknown message type %d\n", dev->name, mesg->type);
455 456 457 458 459
		dev_kfree_skb(skb);
		return -EINVAL;
	}
	dev_kfree_skb(skb);
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
460 461
}

462
static void lec_atm_close(struct atm_vcc *vcc)
Linus Torvalds's avatar
Linus Torvalds committed
463
{
464 465
	struct sk_buff *skb;
	struct net_device *dev = (struct net_device *)vcc->proto_data;
466
	struct lec_priv *priv = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
467

468 469
	priv->lecd = NULL;
	/* Do something needful? */
Linus Torvalds's avatar
Linus Torvalds committed
470

471 472
	netif_stop_queue(dev);
	lec_arp_destroy(priv);
Linus Torvalds's avatar
Linus Torvalds committed
473

474
	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
475
		pr_info("%s closing with messages pending\n", dev->name);
476
	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
477
		atm_return(vcc, skb->truesize);
Linus Torvalds's avatar
Linus Torvalds committed
478
		dev_kfree_skb(skb);
479 480
	}

481
	pr_info("%s: Shut down!\n", dev->name);
482
	module_put(THIS_MODULE);
Linus Torvalds's avatar
Linus Torvalds committed
483 484 485
}

static struct atmdev_ops lecdev_ops = {
486 487
	.close = lec_atm_close,
	.send = lec_atm_send
Linus Torvalds's avatar
Linus Torvalds committed
488 489 490
};

static struct atm_dev lecatm_dev = {
491 492 493
	.ops = &lecdev_ops,
	.type = "lec",
	.number = 999,		/* dummy device number */
494
	.lock = __SPIN_LOCK_UNLOCKED(lecatm_dev.lock)
Linus Torvalds's avatar
Linus Torvalds committed
495 496 497 498 499 500
};

/*
 * LANE2: new argument struct sk_buff *data contains
 * the LE_ARP based TLVs introduced in the LANE2 spec
 */
501 502
static int
send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
503
	     const unsigned char *mac_addr, const unsigned char *atm_addr,
504
	     struct sk_buff *data)
Linus Torvalds's avatar
Linus Torvalds committed
505 506 507 508 509
{
	struct sock *sk;
	struct sk_buff *skb;
	struct atmlec_msg *mesg;

510
	if (!priv || !priv->lecd)
Linus Torvalds's avatar
Linus Torvalds committed
511 512 513 514 515 516
		return -1;
	skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
	if (!skb)
		return -1;
	skb->len = sizeof(struct atmlec_msg);
	mesg = (struct atmlec_msg *)skb->data;
517
	memset(mesg, 0, sizeof(struct atmlec_msg));
Linus Torvalds's avatar
Linus Torvalds committed
518
	mesg->type = type;
519 520
	if (data != NULL)
		mesg->sizeoftlvs = data->len;
Linus Torvalds's avatar
Linus Torvalds committed
521 522
	if (mac_addr)
		memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
523 524
	else
		mesg->content.normal.targetless_le_arp = 1;
Linus Torvalds's avatar
Linus Torvalds committed
525 526 527
	if (atm_addr)
		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);

528
	atm_force_charge(priv->lecd, skb->truesize);
Linus Torvalds's avatar
Linus Torvalds committed
529 530
	sk = sk_atm(priv->lecd);
	skb_queue_tail(&sk->sk_receive_queue, skb);
531
	sk->sk_data_ready(sk, skb->len);
Linus Torvalds's avatar
Linus Torvalds committed
532

533
	if (data != NULL) {
534
		pr_debug("about to send %d bytes of data\n", data->len);
535 536 537 538
		atm_force_charge(priv->lecd, data->truesize);
		skb_queue_tail(&sk->sk_receive_queue, data);
		sk->sk_data_ready(sk, skb->len);
	}
Linus Torvalds's avatar
Linus Torvalds committed
539

540
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
541 542 543 544 545
}

/* shamelessly stolen from drivers/net/net_init.c */
static int lec_change_mtu(struct net_device *dev, int new_mtu)
{
546 547 548 549
	if ((new_mtu < 68) || (new_mtu > 18190))
		return -EINVAL;
	dev->mtu = new_mtu;
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
550 551 552 553
}

static void lec_set_multicast_list(struct net_device *dev)
{
554 555 556 557
	/*
	 * by default, all multicast frames arrive over the bus.
	 * eventually support selective multicast service
	 */
Linus Torvalds's avatar
Linus Torvalds committed
558 559
}

560 561 562 563 564 565
static const struct net_device_ops lec_netdev_ops = {
	.ndo_open		= lec_open,
	.ndo_stop		= lec_close,
	.ndo_start_xmit		= lec_start_xmit,
	.ndo_change_mtu		= lec_change_mtu,
	.ndo_tx_timeout		= lec_tx_timeout,
566
	.ndo_set_rx_mode	= lec_set_multicast_list,
567 568
};

569
static const unsigned char lec_ctrl_magic[] = {
570 571 572 573 574
	0xff,
	0x00,
	0x01,
	0x01
};
Linus Torvalds's avatar
Linus Torvalds committed
575

576 577 578 579
#define LEC_DATA_DIRECT_8023  2
#define LEC_DATA_DIRECT_8025  3

static int lec_is_data_direct(struct atm_vcc *vcc)
580
{
581 582
	return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
		(vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
583
}
584

585
static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
586
{
587
	unsigned long flags;
588
	struct net_device *dev = (struct net_device *)vcc->proto_data;
589
	struct lec_priv *priv = netdev_priv(dev);
Linus Torvalds's avatar
Linus Torvalds committed
590

591
#if DUMP_PACKETS > 0
592 593
	printk(KERN_DEBUG "%s: vcc vpi:%d vci:%d\n",
	       dev->name, vcc->vpi, vcc->vci);
Linus Torvalds's avatar
Linus Torvalds committed
594
#endif
595
	if (!skb) {
596
		pr_debug("%s: null skb\n", dev->name);
597 598 599
		lec_vcc_close(priv, vcc);
		return;
	}
Linus Torvalds's avatar
Linus Torvalds committed
600
#if DUMP_PACKETS >= 2
601
#define MAX_SKB_DUMP 99
Linus Torvalds's avatar
Linus Torvalds committed
602
#elif DUMP_PACKETS >= 1
603 604 605 606 607 608 609
#define MAX_SKB_DUMP 30
#endif
#if DUMP_PACKETS > 0
	printk(KERN_DEBUG "%s: rcv datalen:%ld lecid:%4.4x\n",
	       dev->name, skb->len, priv->lecid);
	print_hex_dump(KERN_DEBUG, "", DUMP_OFFSET, 16, 1,
		       skb->data, min(MAX_SKB_DUMP, skb->len), true);
Linus Torvalds's avatar
Linus Torvalds committed
610
#endif /* DUMP_PACKETS > 0 */
611 612
	if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {
				/* Control frame, to daemon */
Linus Torvalds's avatar
Linus Torvalds committed
613 614
		struct sock *sk = sk_atm(vcc);

615
		pr_debug("%s: To daemon\n", dev->name);
616 617 618
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
	} else {		/* Data frame, queue to protocol handlers */
619
		struct lec_arp_table *entry;
620 621 622
		unsigned char *src, *dst;

		atm_return(vcc, skb->truesize);
Al Viro's avatar
Al Viro committed
623
		if (*(__be16 *) skb->data == htons(priv->lecid) ||
624 625 626 627 628
		    !priv->lecd || !(dev->flags & IFF_UP)) {
			/*
			 * Probably looping back, or if lecd is missing,
			 * lecd has gone down
			 */
629
			pr_debug("Ignoring frame...\n");
630 631 632
			dev_kfree_skb(skb);
			return;
		}
633
		dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
634

635 636
		/*
		 * If this is a Data Direct VCC, and the VCC does not match
637 638 639 640
		 * the LE_ARP cache entry, delete the LE_ARP cache entry.
		 */
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
		if (lec_is_data_direct(vcc)) {
641
			src = ((struct lecdatahdr_8023 *)skb->data)->h_source;
642 643 644
			entry = lec_arp_find(priv, src);
			if (entry && entry->vcc != vcc) {
				lec_arp_remove(priv, entry);
645
				lec_arp_put(entry);
646 647 648
			}
		}
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
649

650 651
		if (!(dst[0] & 0x01) &&	/* Never filter Multi/Broadcast */
		    !priv->is_proxy &&	/* Proxy wants all the packets */
Linus Torvalds's avatar
Linus Torvalds committed
652
		    memcmp(dst, dev->dev_addr, dev->addr_len)) {
653 654 655
			dev_kfree_skb(skb);
			return;
		}
656
		if (!hlist_empty(&priv->lec_arp_empty_ones))
657 658
			lec_arp_check_empties(priv, vcc, skb);
		skb_pull(skb, 2);	/* skip lec_id */
659
		skb->protocol = eth_type_trans(skb, dev);
660 661
		dev->stats.rx_packets++;
		dev->stats.rx_bytes += skb->len;
662 663 664
		memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
		netif_rx(skb);
	}
Linus Torvalds's avatar
Linus Torvalds committed
665 666
}

667
static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
668 669 670 671 672
{
	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
	struct net_device *dev = skb->dev;

	if (vpriv == NULL) {
673
		pr_info("vpriv = NULL!?!?!?\n");
Linus Torvalds's avatar
Linus Torvalds committed
674 675 676 677 678 679 680 681 682 683 684 685
		return;
	}

	vpriv->old_pop(vcc, skb);

	if (vpriv->xoff && atm_may_send(vcc, 0)) {
		vpriv->xoff = 0;
		if (netif_running(dev) && netif_queue_stopped(dev))
			netif_wake_queue(dev);
	}
}

686
static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
Linus Torvalds's avatar
Linus Torvalds committed
687 688
{
	struct lec_vcc_priv *vpriv;
689 690 691 692 693
	int bytes_left;
	struct atmlec_ioc ioc_data;

	/* Lecd must be up in this case */
	bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
694 695
	if (bytes_left != 0)
		pr_info("copy from user failed for %d bytes\n", bytes_left);
696 697 698
	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
	    !dev_lec[ioc_data.dev_num])
		return -EINVAL;
699 700
	vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
	if (!vpriv)
Linus Torvalds's avatar
Linus Torvalds committed
701 702 703 704 705
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
	vcc->pop = lec_pop;
706
	lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]),
707 708 709 710
		      &ioc_data, vcc, vcc->push);
	vcc->proto_data = dev_lec[ioc_data.dev_num];
	vcc->push = lec_push;
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
711 712
}

713
static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
Linus Torvalds's avatar
Linus Torvalds committed
714
{
715 716 717
	if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
		return -EINVAL;
	vcc->proto_data = dev_lec[arg];
718
	return lec_mcast_make(netdev_priv(dev_lec[arg]), vcc);
Linus Torvalds's avatar
Linus Torvalds committed
719 720 721
}

/* Initialize device. */
722 723 724 725 726 727 728 729 730 731 732 733
static int lecd_attach(struct atm_vcc *vcc, int arg)
{
	int i;
	struct lec_priv *priv;

	if (arg < 0)
		i = 0;
	else
		i = arg;
	if (arg >= MAX_LEC_ITF)
		return -EINVAL;
	if (!dev_lec[i]) {
734
		int size;
Linus Torvalds's avatar
Linus Torvalds committed
735

736
		size = sizeof(struct lec_priv);
737
		dev_lec[i] = alloc_etherdev(size);
738 739
		if (!dev_lec[i])
			return -ENOMEM;
740
		dev_lec[i]->netdev_ops = &lec_netdev_ops;
741 742 743 744 745 746
		snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
		if (register_netdev(dev_lec[i])) {
			free_netdev(dev_lec[i]);
			return -EINVAL;
		}

747
		priv = netdev_priv(dev_lec[i]);
748
	} else {
749
		priv = netdev_priv(dev_lec[i]);
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
		if (priv->lecd)
			return -EADDRINUSE;
	}
	lec_arp_init(priv);
	priv->itfnum = i;	/* LANE2 addition */
	priv->lecd = vcc;
	vcc->dev = &lecatm_dev;
	vcc_insert_socket(sk_atm(vcc));

	vcc->proto_data = dev_lec[i];
	set_bit(ATM_VF_META, &vcc->flags);
	set_bit(ATM_VF_READY, &vcc->flags);

	/* Set default values to these variables */
	priv->maximum_unknown_frame_count = 1;
	priv->max_unknown_frame_time = (1 * HZ);
	priv->vcc_timeout_period = (1200 * HZ);
	priv->max_retry_count = 1;
	priv->aging_time = (300 * HZ);
	priv->forward_delay_time = (15 * HZ);
	priv->topology_change = 0;
	priv->arp_response_time = (1 * HZ);
	priv->flush_timeout = (4 * HZ);
	priv->path_switching_delay = (6 * HZ);

775
	if (dev_lec[i]->flags & IFF_UP)
776 777 778
		netif_start_queue(dev_lec[i]);
	__module_get(THIS_MODULE);
	return i;
Linus Torvalds's avatar
Linus Torvalds committed
779 780 781
}

#ifdef CONFIG_PROC_FS
782
static const char *lec_arp_get_status_string(unsigned char status)
Linus Torvalds's avatar
Linus Torvalds committed
783
{
784
	static const char *const lec_arp_status_string[] = {
Linus Torvalds's avatar
Linus Torvalds committed
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
		"ESI_UNKNOWN       ",
		"ESI_ARP_PENDING   ",
		"ESI_VC_PENDING    ",
		"<Undefined>       ",
		"ESI_FLUSH_PENDING ",
		"ESI_FORWARD_DIRECT"
	};

	if (status > ESI_FORWARD_DIRECT)
		status = 3;	/* ESI_UNDEFINED */
	return lec_arp_status_string[status];
}

static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
{
	int i;

	for (i = 0; i < ETH_ALEN; i++)
		seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff);
	seq_printf(seq, " ");
	for (i = 0; i < ATM_ESA_LEN; i++)
		seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff);
	seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status),
		   entry->flags & 0xffff);
	if (entry->vcc)
		seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);
	else
812
		seq_printf(seq, "        ");
Linus Torvalds's avatar
Linus Torvalds committed
813 814 815
	if (entry->recv_vcc) {
		seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,
			   entry->recv_vcc->vci);
816 817
	}
	seq_putc(seq, '\n');
Linus Torvalds's avatar
Linus Torvalds committed
818 819 820 821 822
}

struct lec_state {
	unsigned long flags;
	struct lec_priv *locked;
823
	struct hlist_node *node;
Linus Torvalds's avatar
Linus Torvalds committed
824 825 826 827 828 829
	struct net_device *dev;
	int itf;
	int arp_table;
	int misc_table;
};

830
static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
Linus Torvalds's avatar
Linus Torvalds committed
831 832
			  loff_t *l)
{
833 834
	struct hlist_node *e = state->node;
	struct lec_arp_table *tmp;
Linus Torvalds's avatar
Linus Torvalds committed
835 836

	if (!e)
837
		e = tbl->first;
Joe Perches's avatar
Joe Perches committed
838
	if (e == SEQ_START_TOKEN) {
839
		e = tbl->first;
Linus Torvalds's avatar
Linus Torvalds committed
840 841
		--*l;
	}
842 843

	hlist_for_each_entry_from(tmp, e, next) {
Linus Torvalds's avatar
Linus Torvalds committed
844 845 846
		if (--*l < 0)
			break;
	}
847 848
	state->node = e;

Linus Torvalds's avatar
Linus Torvalds committed
849 850 851 852
	return (*l < 0) ? state : NULL;
}

static void *lec_arp_walk(struct lec_state *state, loff_t *l,
853
			  struct lec_priv *priv)
Linus Torvalds's avatar
Linus Torvalds committed
854 855 856 857 858
{
	void *v = NULL;
	int p;

	for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
859
		v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
Linus Torvalds's avatar
Linus Torvalds committed
860 861 862 863 864 865 866 867 868 869
		if (v)
			break;
	}
	state->arp_table = p;
	return v;
}

static void *lec_misc_walk(struct lec_state *state, loff_t *l,
			   struct lec_priv *priv)
{
870 871 872 873
	struct hlist_head *lec_misc_tables[] = {
		&priv->lec_arp_empty_ones,
		&priv->lec_no_forward,
		&priv->mcast_fwds
Linus Torvalds's avatar
Linus Torvalds committed
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
	};
	void *v = NULL;
	int q;

	for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) {
		v = lec_tbl_walk(state, lec_misc_tables[q], l);
		if (v)
			break;
	}
	state->misc_table = q;
	return v;
}

static void *lec_priv_walk(struct lec_state *state, loff_t *l,
			   struct lec_priv *priv)
{
	if (!state->locked) {
		state->locked = priv;
		spin_lock_irqsave(&priv->lec_arp_lock, state->flags);
	}
894
	if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
Linus Torvalds's avatar
Linus Torvalds committed
895 896 897 898 899 900 901 902 903 904 905 906 907 908
		spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);
		state->locked = NULL;
		/* Partial state reset for the next time we get called */
		state->arp_table = state->misc_table = 0;
	}
	return state->locked;
}

static void *lec_itf_walk(struct lec_state *state, loff_t *l)
{
	struct net_device *dev;
	void *v;

	dev = state->dev ? state->dev : dev_lec[state->itf];
909 910
	v = (dev && netdev_priv(dev)) ?
		lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
Linus Torvalds's avatar
Linus Torvalds committed
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
	if (!v && dev) {
		dev_put(dev);
		/* Partial state reset for the next time we get called */
		dev = NULL;
	}
	state->dev = dev;
	return v;
}

static void *lec_get_idx(struct lec_state *state, loff_t l)
{
	void *v = NULL;

	for (; state->itf < MAX_LEC_ITF; state->itf++) {
		v = lec_itf_walk(state, &l);
		if (v)
			break;
	}
929
	return v;
Linus Torvalds's avatar
Linus Torvalds committed
930 931 932 933 934 935 936 937 938 939 940
}

static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct lec_state *state = seq->private;

	state->itf = 0;
	state->dev = NULL;
	state->locked = NULL;
	state->arp_table = 0;
	state->misc_table = 0;
Joe Perches's avatar
Joe Perches committed
941
	state->node = SEQ_START_TOKEN;
Linus Torvalds's avatar
Linus Torvalds committed
942

Joe Perches's avatar
Joe Perches committed
943
	return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
Linus Torvalds's avatar
Linus Torvalds committed
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
}

static void lec_seq_stop(struct seq_file *seq, void *v)
{
	struct lec_state *state = seq->private;

	if (state->dev) {
		spin_unlock_irqrestore(&state->locked->lec_arp_lock,
				       state->flags);
		dev_put(state->dev);
	}
}

static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct lec_state *state = seq->private;

	v = lec_get_idx(state, 1);
	*pos += !!PTR_ERR(v);
	return v;
}

static int lec_seq_show(struct seq_file *seq, void *v)
{
968 969
	static const char lec_banner[] =
	    "Itf  MAC          ATM destination"
970 971
	    "                          Status            Flags "
	    "VPI/VCI Recv VPI/VCI\n";
Linus Torvalds's avatar
Linus Torvalds committed
972

Joe Perches's avatar
Joe Perches committed
973
	if (v == SEQ_START_TOKEN)
Linus Torvalds's avatar
Linus Torvalds committed
974 975 976
		seq_puts(seq, lec_banner);
	else {
		struct lec_state *state = seq->private;
977
		struct net_device *dev = state->dev;
978 979 980
		struct lec_arp_table *entry = hlist_entry(state->node,
							  struct lec_arp_table,
							  next);
Linus Torvalds's avatar
Linus Torvalds committed
981 982

		seq_printf(seq, "%s ", dev->name);
983
		lec_info(seq, entry);
Linus Torvalds's avatar
Linus Torvalds committed
984 985 986 987
	}
	return 0;
}

988
static const struct seq_operations lec_seq_ops = {
989 990 991 992
	.start = lec_seq_start,
	.next = lec_seq_next,
	.stop = lec_seq_stop,
	.show = lec_seq_show,
Linus Torvalds's avatar
Linus Torvalds committed
993 994 995 996
};

static int lec_seq_open(struct inode *inode, struct file *file)
{
997
	return seq_open_private(file, &lec_seq_ops, sizeof(struct lec_state));
Linus Torvalds's avatar
Linus Torvalds committed
998 999
}

1000
static const struct file_operations lec_seq_fops = {
1001 1002 1003 1004
	.owner = THIS_MODULE,
	.open = lec_seq_open,
	.read = seq_read,
	.llseek = seq_lseek,
1005
	.release = seq_release_private,
Linus Torvalds's avatar
Linus Torvalds committed
1006 1007 1008 1009 1010 1011 1012
};
#endif

static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct atm_vcc *vcc = ATM_SD(sock);
	int err = 0;
1013

Linus Torvalds's avatar
Linus Torvalds committed
1014
	switch (cmd) {
1015 1016 1017 1018 1019 1020 1021 1022
	case ATMLEC_CTRL:
	case ATMLEC_MCAST:
	case ATMLEC_DATA:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		break;
	default:
		return -ENOIOCTLCMD;
Linus Torvalds's avatar
Linus Torvalds committed
1023 1024 1025
	}

	switch (cmd) {
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
	case ATMLEC_CTRL:
		err = lecd_attach(vcc, (int)arg);
		if (err >= 0)
			sock->state = SS_CONNECTED;
		break;
	case ATMLEC_MCAST:
		err = lec_mcast_attach(vcc, (int)arg);
		break;
	case ATMLEC_DATA:
		err = lec_vcc_attach(vcc, (void __user *)arg);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1037 1038 1039 1040 1041 1042
	}

	return err;
}

static struct atm_ioctl lane_ioctl_ops = {
1043 1044
	.owner = THIS_MODULE,
	.ioctl = lane_ioctl,
Linus Torvalds's avatar
Linus Torvalds committed
1045 1046 1047 1048 1049 1050 1051
};

static int __init lane_module_init(void)
{
#ifdef CONFIG_PROC_FS
	struct proc_dir_entry *p;

1052
	p = proc_create("lec", S_IRUGO, atm_proc_root, &lec_seq_fops);
1053
	if (!p) {
1054
		pr_err("Unable to initialize /proc/net/atm/lec\n");
1055 1056
		return -ENOMEM;
	}
Linus Torvalds's avatar
Linus Torvalds committed
1057 1058 1059
#endif

	register_atm_ioctl(&lane_ioctl_ops);
Michal Marek's avatar
Michal Marek committed
1060
	pr_info("lec.c: initialized\n");
1061
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1062 1063 1064 1065
}

static void __exit lane_module_cleanup(void)
{
1066
	int i;
Linus Torvalds's avatar
Linus Torvalds committed
1067 1068 1069 1070 1071

	remove_proc_entry("lec", atm_proc_root);

	deregister_atm_ioctl(&lane_ioctl_ops);

1072 1073
	for (i = 0; i < MAX_LEC_ITF; i++) {
		if (dev_lec[i] != NULL) {
Linus Torvalds's avatar
Linus Torvalds committed
1074
			unregister_netdev(dev_lec[i]);
1075 1076 1077 1078
			free_netdev(dev_lec[i]);
			dev_lec[i] = NULL;
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
}

module_init(lane_module_init);
module_exit(lane_module_cleanup);

/*
 * LANE2: 3.1.3, LE_RESOLVE.request
 * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs.
 * If sizeoftlvs == NULL the default TLVs associated with with this
 * lec will be used.
 * If dst_mac == NULL, targetless LE_ARP will be sent
 */
1091
static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
1092
			 u8 **tlvs, u32 *sizeoftlvs)
Linus Torvalds's avatar
Linus Torvalds committed
1093 1094
{
	unsigned long flags;
1095
	struct lec_priv *priv = netdev_priv(dev);
1096 1097 1098
	struct lec_arp_table *table;
	struct sk_buff *skb;
	int retval;
Linus Torvalds's avatar
Linus Torvalds committed
1099

1100
	if (force == 0) {
Linus Torvalds's avatar
Linus Torvalds committed
1101
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
1102
		table = lec_arp_find(priv, dst_mac);
Linus Torvalds's avatar
Linus Torvalds committed
1103
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1104 1105 1106
		if (table == NULL)
			return -1;

1107
		*tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
1108 1109 1110 1111 1112 1113 1114
		if (*tlvs == NULL)
			return -1;

		*sizeoftlvs = table->sizeoftlvs;

		return 0;
	}
Linus Torvalds's avatar
Linus Torvalds committed
1115 1116 1117

	if (sizeoftlvs == NULL)
		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
1118

Linus Torvalds's avatar
Linus Torvalds committed
1119 1120 1121 1122 1123
	else {
		skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
		if (skb == NULL)
			return -1;
		skb->len = *sizeoftlvs;
1124
		skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);
Linus Torvalds's avatar
Linus Torvalds committed
1125 1126
		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
	}
1127 1128
	return retval;
}
Linus Torvalds's avatar
Linus Torvalds committed
1129 1130 1131 1132 1133 1134 1135 1136

/*
 * LANE2: 3.1.4, LE_ASSOCIATE.request
 * Associate the *tlvs with the *lan_dst address.
 * Will overwrite any previous association
 * Returns 1 for success, 0 for failure (out of memory)
 *
 */
1137 1138
static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
			       const u8 *tlvs, u32 sizeoftlvs)
Linus Torvalds's avatar
Linus Torvalds committed
1139
{
1140 1141
	int retval;
	struct sk_buff *skb;
1142
	struct lec_priv *priv = netdev_priv(dev);
1143

1144
	if (!ether_addr_equal(lan_dst, dev->dev_addr))
1145
		return 0;	/* not our mac address */
1146 1147 1148

	kfree(priv->tlvs);	/* NULL if there was no previous association */

1149
	priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1150
	if (priv->tlvs == NULL)
1151
		return 0;
1152 1153 1154 1155 1156 1157
	priv->sizeoftlvs = sizeoftlvs;

	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
	if (skb == NULL)
		return 0;
	skb->len = sizeoftlvs;
1158
	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
1159 1160
	retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
	if (retval != 0)
1161
		pr_info("lec.c: lane2_associate_req() failed\n");
1162 1163 1164 1165
	/*
	 * If the previous association has changed we must
	 * somehow notify other LANE entities about the change
	 */
1166
	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
1167 1168 1169 1170 1171 1172
}

/*
 * LANE2: 3.1.5, LE_ASSOCIATE.indication
 *
 */
1173 1174
static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
				const u8 *tlvs, u32 sizeoftlvs)
Linus Torvalds's avatar
Linus Torvalds committed
1175 1176
{
#if 0
1177
	int i = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1178
#endif
1179
	struct lec_priv *priv = netdev_priv(dev);
1180 1181 1182 1183 1184 1185 1186
#if 0				/*
				 * Why have the TLVs in LE_ARP entries
				 * since we do not use them? When you
				 * uncomment this code, make sure the
				 * TLVs get freed when entry is killed
				 */
	struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
Linus Torvalds's avatar
Linus Torvalds committed
1187

1188 1189
	if (entry == NULL)
		return;		/* should not happen */
Linus Torvalds's avatar
Linus Torvalds committed
1190

1191
	kfree(entry->tlvs);
Linus Torvalds's avatar
Linus Torvalds committed
1192

1193
	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1194 1195 1196
	if (entry->tlvs == NULL)
		return;
	entry->sizeoftlvs = sizeoftlvs;
Linus Torvalds's avatar
Linus Torvalds committed
1197 1198
#endif
#if 0
1199 1200
	pr_info("\n");
	pr_info("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
1201
	while (i < sizeoftlvs)
1202
		pr_cont("%02x ", tlvs[i++]);
1203

1204
	pr_cont("\n");
Linus Torvalds's avatar
Linus Torvalds committed
1205 1206
#endif

1207 1208 1209 1210 1211
	/* tell MPOA about the TLVs we saw */
	if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
		priv->lane2_ops->associate_indicator(dev, mac_addr,
						     tlvs, sizeoftlvs);
	}
Linus Torvalds's avatar
Linus Torvalds committed
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
}

/*
 * Here starts what used to lec_arpc.c
 *
 * lec_arpc.c was added here when making
 * lane client modular. October 1997
 */

#include <linux/types.h>
#include <linux/timer.h>
1223
#include <linux/param.h>
1224
#include <linux/atomic.h>
Linus Torvalds's avatar
Linus Torvalds committed
1225 1226 1227 1228
#include <linux/inetdevice.h>
#include <net/route.h>

#if 0
1229
#define pr_debug(format, args...)
Linus Torvalds's avatar
Linus Torvalds committed
1230
/*
1231
  #define pr_debug printk
Linus Torvalds's avatar
Linus Torvalds committed
1232 1233 1234 1235 1236 1237
*/
#endif
#define DEBUG_ARP_TABLE 0

#define LEC_ARP_REFRESH_INTERVAL (3*HZ)

1238
static void lec_arp_check_expire(struct work_struct *work);
Linus Torvalds's avatar
Linus Torvalds committed
1239 1240
static void lec_arp_expire_arp(unsigned long data);

1241
/*
Linus Torvalds's avatar
Linus Torvalds committed
1242 1243 1244
 * Arp table funcs
 */

1245
#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE - 1))
Linus Torvalds's avatar
Linus Torvalds committed
1246 1247 1248 1249

/*
 * Initialization of arp-cache
 */
1250
static void lec_arp_init(struct lec_priv *priv)
Linus Torvalds's avatar
Linus Torvalds committed
1251
{
1252
	unsigned short i;
Linus Torvalds's avatar
Linus Torvalds committed
1253

1254
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
1255
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1256 1257 1258
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
	INIT_HLIST_HEAD(&priv->lec_no_forward);
	INIT_HLIST_HEAD(&priv->mcast_fwds);
Linus Torvalds's avatar
Linus Torvalds committed
1259
	spin_lock_init(&priv->lec_arp_lock);
1260
	INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
1261
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
Linus Torvalds's avatar
Linus Torvalds committed
1262 1263
}

1264
static void lec_arp_clear_vccs(struct lec_arp_table *entry)
Linus Torvalds's avatar
Linus Torvalds committed
1265
{
1266
	if (entry->vcc) {
Linus Torvalds's avatar
Linus Torvalds committed
1267 1268
		struct atm_vcc *vcc = entry->vcc;
		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
1269
		struct net_device *dev = (struct net_device *)vcc->proto_data;
Linus Torvalds's avatar
Linus Torvalds committed
1270

1271
		vcc->pop = vpriv->old_pop;
Linus Torvalds's avatar
Linus Torvalds committed
1272 1273 1274 1275
		if (vpriv->xoff)
			netif_wake_queue(dev);
		kfree(vpriv);
		vcc->user_back = NULL;
1276
		vcc->push = entry->old_push;
Linus Torvalds's avatar
Linus Torvalds committed
1277
		vcc_release_async(vcc, -EPIPE);
1278
		entry->vcc = NULL;
1279 1280 1281
	}
	if (entry->recv_vcc) {
		entry->recv_vcc->push = entry->old_recv_push;
Linus Torvalds's avatar
Linus Torvalds committed
1282
		vcc_release_async(entry-><