lec.c 63.4 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * lec.c: Lan Emulation driver
L
Linus Torvalds 已提交
3
 *
4
 * Marko Kiiskila <mkiiskila@yahoo.com>
L
Linus Torvalds 已提交
5 6
 */

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

9
#include <linux/slab.h>
L
Linus Torvalds 已提交
10 11
#include <linux/kernel.h>
#include <linux/bitops.h>
12
#include <linux/capability.h>
L
Linus Torvalds 已提交
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>
J
Joe Perches 已提交
22
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
#include <net/arp.h>
#include <net/dst.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/seq_file.h>

/* TokenRing if needed */
#ifdef CONFIG_TR
#include <linux/trdevice.h>
#endif

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

42
static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
L
Linus Torvalds 已提交
43 44 45 46 47 48 49 50 51 52
#endif

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

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

53 54 55 56 57
#define DUMP_PACKETS 0		/*
				 * 0 = None,
				 * 1 = 30 first bytes
				 * 2 = Whole packet
				 */
L
Linus Torvalds 已提交
58

59 60 61 62
#define LEC_UNRES_QUE_LEN 8	/*
				 * number of tx packets to queue for a
				 * single destination while waiting for SVC
				 */
L
Linus Torvalds 已提交
63 64

static int lec_open(struct net_device *dev);
65 66
static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
				  struct net_device *dev);
L
Linus Torvalds 已提交
67
static int lec_close(struct net_device *dev);
68
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
69
					  const unsigned char *mac_addr);
L
Linus Torvalds 已提交
70
static int lec_arp_remove(struct lec_priv *priv,
71
			  struct lec_arp_table *to_remove);
L
Linus Torvalds 已提交
72
/* LANE2 functions */
73 74 75
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,
76
			 u8 **tlvs, u32 *sizeoftlvs);
77 78
static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
			       const u8 *tlvs, u32 sizeoftlvs);
L
Linus Torvalds 已提交
79

80
static int lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr,
L
Linus Torvalds 已提交
81 82 83 84 85
			   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);
86
static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
87
				       const unsigned char *mac_to_find,
L
Linus Torvalds 已提交
88 89
				       int is_rdesc,
				       struct lec_arp_table **ret_entry);
90
static void lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
J
Joe Perches 已提交
91 92
			   const unsigned char *atm_addr,
			   unsigned long remoteflag,
L
Linus Torvalds 已提交
93 94 95 96
			   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,
97
				  const unsigned char *atm_addr,
L
Linus Torvalds 已提交
98
				  unsigned long tran_id);
J
Joe Perches 已提交
99 100
static void lec_vcc_added(struct lec_priv *priv,
			  const struct atmlec_ioc *ioc_data,
L
Linus Torvalds 已提交
101
			  struct atm_vcc *vcc,
J
Joe Perches 已提交
102 103
			  void (*old_push)(struct atm_vcc *vcc,
					   struct sk_buff *skb));
L
Linus Torvalds 已提交
104 105
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);

106 107 108 109 110 111 112 113 114 115 116 117
/* 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);
}

L
Linus Torvalds 已提交
118
static struct lane2_ops lane2_ops = {
119 120 121
	lane2_resolve,		/* resolve,             spec 3.1.3 */
	lane2_associate_req,	/* associate_req,       spec 3.1.4 */
	NULL			/* associate indicator, spec 3.1.5 */
L
Linus Torvalds 已提交
122 123
};

124
static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
L
Linus Torvalds 已提交
125 126 127 128 129 130 131

/* 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)
{
132 133 134 135 136 137 138 139 140 141 142 143
	struct ethhdr *eth;
	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
	 */
	eth = (struct ethhdr *)skb->data;
	buff = skb->data + skb->dev->hard_header_len;
	if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
L
Linus Torvalds 已提交
144
		struct sock *sk;
145 146 147 148 149 150 151 152 153 154
		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;
J
Joe Perches 已提交
155 156
		mesg->content.normal.flag = *buff & 0x01;
					/* 0x01 is topology change */
157

158
		priv = netdev_priv(dev);
159
		atm_force_charge(priv->lecd, skb2->truesize);
L
Linus Torvalds 已提交
160
		sk = sk_atm(priv->lecd);
161 162 163
		skb_queue_tail(&sk->sk_receive_queue, skb2);
		sk->sk_data_ready(sk, skb2->len);
	}
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
}
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */

/*
 * Modelled after tr_type_trans
 * All multicast and ARE or STE frames go to BUS.
 * Non source routed frames go by destination address.
 * Last hop source routed frames go by destination address.
 * Not last hop source routed frames go by _next_ route descriptor.
 * Returns pointer to destination MAC address or fills in rdesc
 * and returns NULL.
 */
#ifdef CONFIG_TR
static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
{
179
	struct trh_hdr *trh;
180
	unsigned int riflen, num_rdsc;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

	trh = (struct trh_hdr *)packet;
	if (trh->daddr[0] & (uint8_t) 0x80)
		return bus_mac;	/* multicast */

	if (trh->saddr[0] & TR_RII) {
		riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
		if ((ntohs(trh->rcf) >> 13) != 0)
			return bus_mac;	/* ARE or STE */
	} else
		return trh->daddr;	/* not source routed */

	if (riflen < 6)
		return trh->daddr;	/* last hop, source routed */

	/* riflen is 6 or more, packet has more than one route descriptor */
	num_rdsc = (riflen / 2) - 1;
	memset(rdesc, 0, ETH_ALEN);
	/* offset 4 comes from LAN destination field in LE control frames */
	if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT))
A
Al Viro 已提交
201
		memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(__be16));
202
	else {
A
Al Viro 已提交
203
		memcpy(&rdesc[4], &trh->rseg[1], sizeof(__be16));
204 205 206 207
		rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
	}

	return NULL;
L
Linus Torvalds 已提交
208 209 210 211 212 213 214 215 216 217 218 219
}
#endif /* CONFIG_TR */

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

220
static int lec_open(struct net_device *dev)
L
Linus Torvalds 已提交
221 222
{
	netif_start_queue(dev);
223 224

	return 0;
L
Linus Torvalds 已提交
225 226
}

227 228
static void
lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
229
{
230 231
	struct net_device *dev = skb->dev;

L
Linus Torvalds 已提交
232 233 234 235 236
	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) {
237
		dev->stats.tx_dropped++;
L
Linus Torvalds 已提交
238 239 240
		return;
	}

241 242
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;
L
Linus Torvalds 已提交
243 244
}

245
static void lec_tx_timeout(struct net_device *dev)
L
Linus Torvalds 已提交
246
{
247
	pr_info("%s\n", dev->name);
L
Linus Torvalds 已提交
248 249 250 251
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}

252 253
static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
				  struct net_device *dev)
L
Linus Torvalds 已提交
254
{
255
	struct sk_buff *skb2;
256
	struct lec_priv *priv = netdev_priv(dev);
257 258
	struct lecdatahdr_8023 *lec_h;
	struct atm_vcc *vcc;
L
Linus Torvalds 已提交
259
	struct lec_arp_table *entry;
260
	unsigned char *dst;
L
Linus Torvalds 已提交
261 262
	int min_frame_size;
#ifdef CONFIG_TR
263
	unsigned char rdesc[ETH_ALEN];	/* Token Ring route descriptor */
L
Linus Torvalds 已提交
264
#endif
265 266
	int is_rdesc;

267
	pr_debug("called\n");
268
	if (!priv->lecd) {
J
Joe Perches 已提交
269
		pr_info("%s:No lecd attached\n", dev->name);
270
		dev->stats.tx_errors++;
271
		netif_stop_queue(dev);
272 273
		kfree_skb(skb);
		return NETDEV_TX_OK;
274 275
	}

276
	pr_debug("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
277 278
		 (long)skb->head, (long)skb->data, (long)skb_tail_pointer(skb),
		 (long)skb_end_pointer(skb));
L
Linus Torvalds 已提交
279
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
280 281
	if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
		lec_handle_bridge(skb, dev);
L
Linus Torvalds 已提交
282 283
#endif

284 285
	/* Make sure we have room for lec_id */
	if (skb_headroom(skb) < 2) {
286
		pr_debug("reallocating skb\n");
287 288 289
		skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
		kfree_skb(skb);
		if (skb2 == NULL)
290
			return NETDEV_TX_OK;
291 292 293
		skb = skb2;
	}
	skb_push(skb, 2);
L
Linus Torvalds 已提交
294

295 296 297
	/* Put le header to place, works for TokenRing too */
	lec_h = (struct lecdatahdr_8023 *)skb->data;
	lec_h->le_header = htons(priv->lecid);
L
Linus Torvalds 已提交
298 299

#ifdef CONFIG_TR
300 301 302 303 304 305 306 307
	/*
	 * Ugly. Use this to realign Token Ring packets for
	 * e.g. PCA-200E driver.
	 */
	if (priv->is_trdev) {
		skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
		kfree_skb(skb);
		if (skb2 == NULL)
308
			return NETDEV_TX_OK;
309 310
		skb = skb2;
	}
L
Linus Torvalds 已提交
311 312 313
#endif

#if DUMP_PACKETS >= 2
J
Joe Perches 已提交
314
#define MAX_DUMP_SKB 99
L
Linus Torvalds 已提交
315
#elif DUMP_PACKETS >= 1
J
Joe Perches 已提交
316 317 318 319 320 321 322
#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);
L
Linus Torvalds 已提交
323 324
#endif /* DUMP_PACKETS >= 1 */

325
	/* Minimum ethernet-frame size */
L
Linus Torvalds 已提交
326
#ifdef CONFIG_TR
327 328
	if (priv->is_trdev)
		min_frame_size = LEC_MINIMUM_8025_SIZE;
L
Linus Torvalds 已提交
329 330
	else
#endif
331 332 333 334 335 336 337 338
		min_frame_size = LEC_MINIMUM_8023_SIZE;
	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) {
339
				dev->stats.tx_dropped++;
340
				return NETDEV_TX_OK;
341 342 343
			}
			skb = skb2;
		}
L
Linus Torvalds 已提交
344
		skb_put(skb, min_frame_size - skb->len);
345 346 347 348 349
	}

	/* Send to right vcc */
	is_rdesc = 0;
	dst = lec_h->h_dest;
L
Linus Torvalds 已提交
350
#ifdef CONFIG_TR
351 352 353 354 355 356 357
	if (priv->is_trdev) {
		dst = get_tr_dst(skb->data + 2, rdesc);
		if (dst == NULL) {
			dst = rdesc;
			is_rdesc = 1;
		}
	}
L
Linus Torvalds 已提交
358
#endif
359 360
	entry = NULL;
	vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
361 362
	pr_debug("%s:vcc:%p vcc_flags:%lx, entry:%p\n",
		 dev->name, vcc, vcc ? vcc->flags : 0, entry);
363 364
	if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) {
		if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
365 366
			pr_debug("%s:queuing packet, MAC address %pM\n",
				 dev->name, lec_h->h_dest);
367 368
			skb_queue_tail(&entry->tx_wait, skb);
		} else {
369 370
			pr_debug("%s:tx queue full or no arp entry, dropping, MAC address: %pM\n",
				 dev->name, lec_h->h_dest);
371
			dev->stats.tx_dropped++;
372 373
			dev_kfree_skb(skb);
		}
374
		goto out;
375 376
	}
#if DUMP_PACKETS > 0
J
Joe Perches 已提交
377 378
	printk(KERN_DEBUG "%s:sending to vpi:%d vci:%d\n",
	       dev->name, vcc->vpi, vcc->vci);
L
Linus Torvalds 已提交
379
#endif /* DUMP_PACKETS > 0 */
380 381

	while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
382
		pr_debug("emptying tx queue, MAC address %pM\n", lec_h->h_dest);
383
		lec_send(vcc, skb2);
384
	}
L
Linus Torvalds 已提交
385

386
	lec_send(vcc, skb);
L
Linus Torvalds 已提交
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403

	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);
	}

404 405 406
out:
	if (entry)
		lec_arp_put(entry);
L
Linus Torvalds 已提交
407
	dev->trans_start = jiffies;
408
	return NETDEV_TX_OK;
L
Linus Torvalds 已提交
409 410 411
}

/* The inverse routine to net_open(). */
412
static int lec_close(struct net_device *dev)
L
Linus Torvalds 已提交
413
{
414 415
	netif_stop_queue(dev);
	return 0;
L
Linus Torvalds 已提交
416 417
}

418
static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
419 420
{
	unsigned long flags;
421
	struct net_device *dev = (struct net_device *)vcc->proto_data;
422
	struct lec_priv *priv = netdev_priv(dev);
423 424 425 426
	struct atmlec_msg *mesg;
	struct lec_arp_table *entry;
	int i;
	char *tmp;		/* FIXME */
L
Linus Torvalds 已提交
427 428

	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
429 430 431
	mesg = (struct atmlec_msg *)skb->data;
	tmp = skb->data;
	tmp += sizeof(struct atmlec_msg);
432
	pr_debug("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
433 434
	switch (mesg->type) {
	case l_set_mac_addr:
J
Joe Perches 已提交
435
		for (i = 0; i < 6; i++)
436 437 438
			dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
		break;
	case l_del_mac_addr:
J
Joe Perches 已提交
439
		for (i = 0; i < 6; i++)
440 441 442 443 444 445 446 447 448 449 450 451 452
			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 */
L
Linus Torvalds 已提交
453
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
454 455
		entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
		lec_arp_remove(priv, entry);
L
Linus Torvalds 已提交
456 457
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

458 459 460 461 462 463 464 465
		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);
466
		pr_debug("in l_arp_update\n");
467
		if (mesg->sizeoftlvs != 0) {	/* LANE2 3.1.5 */
468 469
			pr_debug("LANE2 3.1.5, got tlvs, size %d\n",
				 mesg->sizeoftlvs);
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
			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);
J
Joe Perches 已提交
488 489
		priv->lane_version = mesg->content.config.lane_version;
					/* LANE2 */
L
Linus Torvalds 已提交
490 491 492
		priv->lane2_ops = NULL;
		if (priv->lane_version > 1)
			priv->lane2_ops = &lane2_ops;
S
Stephen Hemminger 已提交
493
		if (dev_set_mtu(dev, mesg->content.config.mtu))
J
Joe Perches 已提交
494 495
			pr_info("%s: change_mtu to %d failed\n",
				dev->name, mesg->content.config.mtu);
L
Linus Torvalds 已提交
496
		priv->is_proxy = mesg->content.config.is_proxy;
497 498 499 500 501 502 503 504 505 506
		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:
L
Linus Torvalds 已提交
507
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
508 509 510
	{
		pr_debug("%s: bridge zeppelin asks about %pM\n",
			 dev->name, mesg->content.proxy.mac_addr);
511

512 513
		if (br_fdb_test_addr_hook == NULL)
			break;
514

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
		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);
531
		}
532
	}
L
Linus Torvalds 已提交
533
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
534 535
		break;
	default:
J
Joe Perches 已提交
536
		pr_info("%s: Unknown message type %d\n", dev->name, mesg->type);
537 538 539 540 541
		dev_kfree_skb(skb);
		return -EINVAL;
	}
	dev_kfree_skb(skb);
	return 0;
L
Linus Torvalds 已提交
542 543
}

544
static void lec_atm_close(struct atm_vcc *vcc)
L
Linus Torvalds 已提交
545
{
546 547
	struct sk_buff *skb;
	struct net_device *dev = (struct net_device *)vcc->proto_data;
548
	struct lec_priv *priv = netdev_priv(dev);
L
Linus Torvalds 已提交
549

550 551
	priv->lecd = NULL;
	/* Do something needful? */
L
Linus Torvalds 已提交
552

553 554
	netif_stop_queue(dev);
	lec_arp_destroy(priv);
L
Linus Torvalds 已提交
555

556
	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
J
Joe Perches 已提交
557
		pr_info("%s closing with messages pending\n", dev->name);
558
	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
559
		atm_return(vcc, skb->truesize);
L
Linus Torvalds 已提交
560
		dev_kfree_skb(skb);
561 562
	}

J
Joe Perches 已提交
563
	pr_info("%s: Shut down!\n", dev->name);
564
	module_put(THIS_MODULE);
L
Linus Torvalds 已提交
565 566 567
}

static struct atmdev_ops lecdev_ops = {
568 569
	.close = lec_atm_close,
	.send = lec_atm_send
L
Linus Torvalds 已提交
570 571 572
};

static struct atm_dev lecatm_dev = {
573 574 575
	.ops = &lecdev_ops,
	.type = "lec",
	.number = 999,		/* dummy device number */
576
	.lock = __SPIN_LOCK_UNLOCKED(lecatm_dev.lock)
L
Linus Torvalds 已提交
577 578 579 580 581 582
};

/*
 * LANE2: new argument struct sk_buff *data contains
 * the LE_ARP based TLVs introduced in the LANE2 spec
 */
583 584
static int
send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
585
	     const unsigned char *mac_addr, const unsigned char *atm_addr,
586
	     struct sk_buff *data)
L
Linus Torvalds 已提交
587 588 589 590 591
{
	struct sock *sk;
	struct sk_buff *skb;
	struct atmlec_msg *mesg;

J
Joe Perches 已提交
592
	if (!priv || !priv->lecd)
L
Linus Torvalds 已提交
593 594 595 596 597 598
		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;
599
	memset(mesg, 0, sizeof(struct atmlec_msg));
L
Linus Torvalds 已提交
600
	mesg->type = type;
601 602
	if (data != NULL)
		mesg->sizeoftlvs = data->len;
L
Linus Torvalds 已提交
603 604
	if (mac_addr)
		memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
605 606
	else
		mesg->content.normal.targetless_le_arp = 1;
L
Linus Torvalds 已提交
607 608 609
	if (atm_addr)
		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);

610
	atm_force_charge(priv->lecd, skb->truesize);
L
Linus Torvalds 已提交
611 612
	sk = sk_atm(priv->lecd);
	skb_queue_tail(&sk->sk_receive_queue, skb);
613
	sk->sk_data_ready(sk, skb->len);
L
Linus Torvalds 已提交
614

615
	if (data != NULL) {
616
		pr_debug("about to send %d bytes of data\n", data->len);
617 618 619 620
		atm_force_charge(priv->lecd, data->truesize);
		skb_queue_tail(&sk->sk_receive_queue, data);
		sk->sk_data_ready(sk, skb->len);
	}
L
Linus Torvalds 已提交
621

622
	return 0;
L
Linus Torvalds 已提交
623 624 625 626 627
}

/* shamelessly stolen from drivers/net/net_init.c */
static int lec_change_mtu(struct net_device *dev, int new_mtu)
{
628 629 630 631
	if ((new_mtu < 68) || (new_mtu > 18190))
		return -EINVAL;
	dev->mtu = new_mtu;
	return 0;
L
Linus Torvalds 已提交
632 633 634 635
}

static void lec_set_multicast_list(struct net_device *dev)
{
636 637 638 639
	/*
	 * by default, all multicast frames arrive over the bus.
	 * eventually support selective multicast service
	 */
L
Linus Torvalds 已提交
640 641
}

642 643 644 645 646 647 648 649 650
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,
	.ndo_set_multicast_list	= lec_set_multicast_list,
};

651
static const unsigned char lec_ctrl_magic[] = {
652 653 654 655 656
	0xff,
	0x00,
	0x01,
	0x01
};
L
Linus Torvalds 已提交
657

658 659 660 661
#define LEC_DATA_DIRECT_8023  2
#define LEC_DATA_DIRECT_8025  3

static int lec_is_data_direct(struct atm_vcc *vcc)
662
{
663 664
	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));
665
}
666

667
static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
668
{
669
	unsigned long flags;
670
	struct net_device *dev = (struct net_device *)vcc->proto_data;
671
	struct lec_priv *priv = netdev_priv(dev);
L
Linus Torvalds 已提交
672

J
Joe Perches 已提交
673
#if DUMP_PACKETS > 0
674 675
	printk(KERN_DEBUG "%s: vcc vpi:%d vci:%d\n",
	       dev->name, vcc->vpi, vcc->vci);
L
Linus Torvalds 已提交
676
#endif
677
	if (!skb) {
678
		pr_debug("%s: null skb\n", dev->name);
679 680 681
		lec_vcc_close(priv, vcc);
		return;
	}
L
Linus Torvalds 已提交
682
#if DUMP_PACKETS >= 2
683
#define MAX_SKB_DUMP 99
L
Linus Torvalds 已提交
684
#elif DUMP_PACKETS >= 1
685 686 687 688 689 690 691
#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);
L
Linus Torvalds 已提交
692
#endif /* DUMP_PACKETS > 0 */
693 694
	if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {
				/* Control frame, to daemon */
L
Linus Torvalds 已提交
695 696
		struct sock *sk = sk_atm(vcc);

697
		pr_debug("%s: To daemon\n", dev->name);
698 699 700
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
	} else {		/* Data frame, queue to protocol handlers */
701
		struct lec_arp_table *entry;
702 703 704
		unsigned char *src, *dst;

		atm_return(vcc, skb->truesize);
A
Al Viro 已提交
705
		if (*(__be16 *) skb->data == htons(priv->lecid) ||
706 707 708 709 710
		    !priv->lecd || !(dev->flags & IFF_UP)) {
			/*
			 * Probably looping back, or if lecd is missing,
			 * lecd has gone down
			 */
711
			pr_debug("Ignoring frame...\n");
712 713 714
			dev_kfree_skb(skb);
			return;
		}
L
Linus Torvalds 已提交
715
#ifdef CONFIG_TR
716 717 718
		if (priv->is_trdev)
			dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
		else
L
Linus Torvalds 已提交
719
#endif
720
			dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
721

722 723
		/*
		 * If this is a Data Direct VCC, and the VCC does not match
724 725 726 727 728 729
		 * 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)) {
#ifdef CONFIG_TR
			if (priv->is_trdev)
730 731 732
				src =
				    ((struct lecdatahdr_8025 *)skb->data)->
				    h_source;
733 734
			else
#endif
735 736 737
				src =
				    ((struct lecdatahdr_8023 *)skb->data)->
				    h_source;
738 739 740
			entry = lec_arp_find(priv, src);
			if (entry && entry->vcc != vcc) {
				lec_arp_remove(priv, entry);
741
				lec_arp_put(entry);
742 743 744
			}
		}
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
L
Linus Torvalds 已提交
745

746 747
		if (!(dst[0] & 0x01) &&	/* Never filter Multi/Broadcast */
		    !priv->is_proxy &&	/* Proxy wants all the packets */
L
Linus Torvalds 已提交
748
		    memcmp(dst, dev->dev_addr, dev->addr_len)) {
749 750 751
			dev_kfree_skb(skb);
			return;
		}
J
Joe Perches 已提交
752
		if (!hlist_empty(&priv->lec_arp_empty_ones))
753 754
			lec_arp_check_empties(priv, vcc, skb);
		skb_pull(skb, 2);	/* skip lec_id */
L
Linus Torvalds 已提交
755
#ifdef CONFIG_TR
756 757 758
		if (priv->is_trdev)
			skb->protocol = tr_type_trans(skb, dev);
		else
L
Linus Torvalds 已提交
759
#endif
760
			skb->protocol = eth_type_trans(skb, dev);
761 762
		dev->stats.rx_packets++;
		dev->stats.rx_bytes += skb->len;
763 764 765
		memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
		netif_rx(skb);
	}
L
Linus Torvalds 已提交
766 767
}

768
static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
769 770 771 772 773
{
	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
	struct net_device *dev = skb->dev;

	if (vpriv == NULL) {
774
		pr_info("vpriv = NULL!?!?!?\n");
L
Linus Torvalds 已提交
775 776 777 778 779 780 781 782 783 784 785 786
		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);
	}
}

787
static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
L
Linus Torvalds 已提交
788 789
{
	struct lec_vcc_priv *vpriv;
790 791 792 793 794
	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));
795 796
	if (bytes_left != 0)
		pr_info("copy from user failed for %d bytes\n", bytes_left);
797 798 799
	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
	    !dev_lec[ioc_data.dev_num])
		return -EINVAL;
J
Joe Perches 已提交
800 801
	vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
	if (!vpriv)
L
Linus Torvalds 已提交
802 803 804 805 806
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
	vcc->pop = lec_pop;
807
	lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]),
808 809 810 811
		      &ioc_data, vcc, vcc->push);
	vcc->proto_data = dev_lec[ioc_data.dev_num];
	vcc->push = lec_push;
	return 0;
L
Linus Torvalds 已提交
812 813
}

814
static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
L
Linus Torvalds 已提交
815
{
816 817 818
	if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
		return -EINVAL;
	vcc->proto_data = dev_lec[arg];
819
	return lec_mcast_make(netdev_priv(dev_lec[arg]), vcc);
L
Linus Torvalds 已提交
820 821 822
}

/* Initialize device. */
823 824 825 826 827 828 829 830 831
static int lecd_attach(struct atm_vcc *vcc, int arg)
{
	int i;
	struct lec_priv *priv;

	if (arg < 0)
		i = 0;
	else
		i = arg;
L
Linus Torvalds 已提交
832
#ifdef CONFIG_TR
833 834 835 836 837
	if (arg >= MAX_LEC_ITF)
		return -EINVAL;
#else				/* Reserve the top NUM_TR_DEVS for TR */
	if (arg >= (MAX_LEC_ITF - NUM_TR_DEVS))
		return -EINVAL;
L
Linus Torvalds 已提交
838
#endif
839 840
	if (!dev_lec[i]) {
		int is_trdev, size;
L
Linus Torvalds 已提交
841

842 843 844
		is_trdev = 0;
		if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
			is_trdev = 1;
L
Linus Torvalds 已提交
845

846
		size = sizeof(struct lec_priv);
L
Linus Torvalds 已提交
847
#ifdef CONFIG_TR
848 849 850
		if (is_trdev)
			dev_lec[i] = alloc_trdev(size);
		else
L
Linus Torvalds 已提交
851
#endif
852 853 854
			dev_lec[i] = alloc_etherdev(size);
		if (!dev_lec[i])
			return -ENOMEM;
855
		dev_lec[i]->netdev_ops = &lec_netdev_ops;
856 857 858 859 860 861
		snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
		if (register_netdev(dev_lec[i])) {
			free_netdev(dev_lec[i]);
			return -EINVAL;
		}

862
		priv = netdev_priv(dev_lec[i]);
863 864
		priv->is_trdev = is_trdev;
	} else {
865
		priv = netdev_priv(dev_lec[i]);
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
		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);

J
Joe Perches 已提交
891
	if (dev_lec[i]->flags & IFF_UP)
892 893 894
		netif_start_queue(dev_lec[i]);
	__module_get(THIS_MODULE);
	return i;
L
Linus Torvalds 已提交
895 896 897
}

#ifdef CONFIG_PROC_FS
898
static const char *lec_arp_get_status_string(unsigned char status)
L
Linus Torvalds 已提交
899
{
900
	static const char *const lec_arp_status_string[] = {
L
Linus Torvalds 已提交
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
		"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
928
		seq_printf(seq, "        ");
L
Linus Torvalds 已提交
929 930 931
	if (entry->recv_vcc) {
		seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,
			   entry->recv_vcc->vci);
932 933
	}
	seq_putc(seq, '\n');
L
Linus Torvalds 已提交
934 935 936 937 938
}

struct lec_state {
	unsigned long flags;
	struct lec_priv *locked;
939
	struct hlist_node *node;
L
Linus Torvalds 已提交
940 941 942 943 944 945
	struct net_device *dev;
	int itf;
	int arp_table;
	int misc_table;
};

946
static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
L
Linus Torvalds 已提交
947 948
			  loff_t *l)
{
949 950
	struct hlist_node *e = state->node;
	struct lec_arp_table *tmp;
L
Linus Torvalds 已提交
951 952

	if (!e)
953
		e = tbl->first;
J
Joe Perches 已提交
954
	if (e == SEQ_START_TOKEN) {
955
		e = tbl->first;
L
Linus Torvalds 已提交
956 957
		--*l;
	}
958 959

	hlist_for_each_entry_from(tmp, e, next) {
L
Linus Torvalds 已提交
960 961 962
		if (--*l < 0)
			break;
	}
963 964
	state->node = e;

L
Linus Torvalds 已提交
965 966 967 968
	return (*l < 0) ? state : NULL;
}

static void *lec_arp_walk(struct lec_state *state, loff_t *l,
969
			  struct lec_priv *priv)
L
Linus Torvalds 已提交
970 971 972 973 974
{
	void *v = NULL;
	int p;

	for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
975
		v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
L
Linus Torvalds 已提交
976 977 978 979 980 981 982 983 984 985
		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)
{
986 987 988 989
	struct hlist_head *lec_misc_tables[] = {
		&priv->lec_arp_empty_ones,
		&priv->lec_no_forward,
		&priv->mcast_fwds
L
Linus Torvalds 已提交
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
	};
	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);
	}
1010
	if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
L
Linus Torvalds 已提交
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
		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];
1025 1026
	v = (dev && netdev_priv(dev)) ?
		lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
L
Linus Torvalds 已提交
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
	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;
	}
1045
	return v;
L
Linus Torvalds 已提交
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
}

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;
J
Joe Perches 已提交
1057
	state->node = SEQ_START_TOKEN;
L
Linus Torvalds 已提交
1058

J
Joe Perches 已提交
1059
	return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
L
Linus Torvalds 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
}

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)
{
1084 1085
	static const char lec_banner[] =
	    "Itf  MAC          ATM destination"
1086 1087
	    "                          Status            Flags "
	    "VPI/VCI Recv VPI/VCI\n";
L
Linus Torvalds 已提交
1088

J
Joe Perches 已提交
1089
	if (v == SEQ_START_TOKEN)
L
Linus Torvalds 已提交
1090 1091 1092
		seq_puts(seq, lec_banner);
	else {
		struct lec_state *state = seq->private;
1093
		struct net_device *dev = state->dev;
J
Joe Perches 已提交
1094 1095 1096
		struct lec_arp_table *entry = hlist_entry(state->node,
							  struct lec_arp_table,
							  next);
L
Linus Torvalds 已提交
1097 1098

		seq_printf(seq, "%s ", dev->name);
1099
		lec_info(seq, entry);
L
Linus Torvalds 已提交
1100 1101 1102 1103
	}
	return 0;
}

1104
static const struct seq_operations lec_seq_ops = {
1105 1106 1107 1108
	.start = lec_seq_start,
	.next = lec_seq_next,
	.stop = lec_seq_stop,
	.show = lec_seq_show,
L
Linus Torvalds 已提交
1109 1110 1111 1112
};

static int lec_seq_open(struct inode *inode, struct file *file)
{
1113
	return seq_open_private(file, &lec_seq_ops, sizeof(struct lec_state));
L
Linus Torvalds 已提交
1114 1115
}

1116
static const struct file_operations lec_seq_fops = {
1117 1118 1119 1120
	.owner = THIS_MODULE,
	.open = lec_seq_open,
	.read = seq_read,
	.llseek = seq_lseek,
1121
	.release = seq_release_private,
L
Linus Torvalds 已提交
1122 1123 1124 1125 1126 1127 1128
};
#endif

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

L
Linus Torvalds 已提交
1130
	switch (cmd) {
1131 1132 1133 1134 1135 1136 1137 1138
	case ATMLEC_CTRL:
	case ATMLEC_MCAST:
	case ATMLEC_DATA:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		break;
	default:
		return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
1139 1140 1141
	}

	switch (cmd) {
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
	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;
L
Linus Torvalds 已提交
1153 1154 1155 1156 1157 1158
	}

	return err;
}

static struct atm_ioctl lane_ioctl_ops = {
1159 1160
	.owner = THIS_MODULE,
	.ioctl = lane_ioctl,
L
Linus Torvalds 已提交
1161 1162 1163 1164 1165 1166 1167
};

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

1168
	p = proc_create("lec", S_IRUGO, atm_proc_root, &lec_seq_fops);
1169
	if (!p) {
1170
		pr_err("Unable to initialize /proc/net/atm/lec\n");
1171 1172
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
1173 1174 1175
#endif

	register_atm_ioctl(&lane_ioctl_ops);
M
Michal Marek 已提交
1176
	pr_info("lec.c: initialized\n");
1177
	return 0;
L
Linus Torvalds 已提交
1178 1179 1180 1181
}

static void __exit lane_module_cleanup(void)
{
1182 1183
	int i;
	struct lec_priv *priv;
L
Linus Torvalds 已提交
1184 1185 1186 1187 1188

	remove_proc_entry("lec", atm_proc_root);

	deregister_atm_ioctl(&lane_ioctl_ops);

1189 1190
	for (i = 0; i < MAX_LEC_ITF; i++) {
		if (dev_lec[i] != NULL) {
1191
			priv = netdev_priv(dev_lec[i]);
L
Linus Torvalds 已提交
1192
			unregister_netdev(dev_lec[i]);
1193 1194 1195 1196
			free_netdev(dev_lec[i]);
			dev_lec[i] = NULL;
		}
	}
L
Linus Torvalds 已提交
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
}

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
 */
1209
static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
1210
			 u8 **tlvs, u32 *sizeoftlvs)
L
Linus Torvalds 已提交
1211 1212
{
	unsigned long flags;
1213
	struct lec_priv *priv = netdev_priv(dev);
1214 1215 1216
	struct lec_arp_table *table;
	struct sk_buff *skb;
	int retval;
L
Linus Torvalds 已提交
1217

1218
	if (force == 0) {
L
Linus Torvalds 已提交
1219
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
1220
		table = lec_arp_find(priv, dst_mac);
L
Linus Torvalds 已提交
1221
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1222 1223 1224
		if (table == NULL)
			return -1;

1225
		*tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
1226 1227 1228 1229 1230 1231 1232
		if (*tlvs == NULL)
			return -1;

		*sizeoftlvs = table->sizeoftlvs;

		return 0;
	}
L
Linus Torvalds 已提交
1233 1234 1235

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

L
Linus Torvalds 已提交
1237 1238 1239 1240 1241
	else {
		skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
		if (skb == NULL)
			return -1;
		skb->len = *sizeoftlvs;
1242
		skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);
L
Linus Torvalds 已提交
1243 1244
		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
	}
1245 1246
	return retval;
}
L
Linus Torvalds 已提交
1247 1248 1249 1250 1251 1252 1253 1254

/*
 * 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)
 *
 */
1255 1256
static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
			       const u8 *tlvs, u32 sizeoftlvs)
L
Linus Torvalds 已提交
1257
{
1258 1259
	int retval;
	struct sk_buff *skb;
1260
	struct lec_priv *priv = netdev_priv(dev);
1261 1262

	if (compare_ether_addr(lan_dst, dev->dev_addr))
J
Joe Perches 已提交
1263
		return 0;	/* not our mac address */
1264 1265 1266

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

1267
	priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1268
	if (priv->tlvs == NULL)
J
Joe Perches 已提交
1269
		return 0;
1270 1271 1272 1273 1274 1275
	priv->sizeoftlvs = sizeoftlvs;

	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
	if (skb == NULL)
		return 0;
	skb->len = sizeoftlvs;
1276
	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
1277 1278
	retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
	if (retval != 0)
J
Joe Perches 已提交
1279
		pr_info("lec.c: lane2_associate_req() failed\n");
1280 1281 1282 1283
	/*
	 * If the previous association has changed we must
	 * somehow notify other LANE entities about the change
	 */
J
Joe Perches 已提交
1284
	return 1;
L
Linus Torvalds 已提交
1285 1286 1287 1288 1289 1290
}

/*
 * LANE2: 3.1.5, LE_ASSOCIATE.indication
 *
 */
1291 1292
static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
				const u8 *tlvs, u32 sizeoftlvs)
L
Linus Torvalds 已提交
1293 1294
{
#if 0
1295
	int i = 0;
L
Linus Torvalds 已提交
1296
#endif
1297
	struct lec_priv *priv = netdev_priv(dev);
1298 1299 1300 1301 1302 1303 1304
#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);
L
Linus Torvalds 已提交
1305

1306 1307
	if (entry == NULL)
		return;		/* should not happen */
L
Linus Torvalds 已提交
1308

1309
	kfree(entry->tlvs);
L
Linus Torvalds 已提交
1310

1311
	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1312 1313 1314
	if (entry->tlvs == NULL)
		return;
	entry->sizeoftlvs = sizeoftlvs;
L
Linus Torvalds 已提交
1315 1316
#endif
#if 0
J
Joe Perches 已提交
1317 1318
	pr_info("\n");
	pr_info("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
1319
	while (i < sizeoftlvs)
J
Joe Perches 已提交
1320
		pr_cont("%02x ", tlvs[i++]);
1321

J
Joe Perches 已提交
1322
	pr_cont("\n");
L
Linus Torvalds 已提交
1323 1324
#endif

1325 1326 1327 1328 1329
	/* 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);
	}
L
Linus Torvalds 已提交
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
}

/*
 * 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>
J
Joe Perches 已提交
1341
#include <linux/param.h>
L
Linus Torvalds 已提交
1342 1343 1344 1345 1346
#include <asm/atomic.h>
#include <linux/inetdevice.h>
#include <net/route.h>

#if 0
J
Joe Perches 已提交
1347
#define pr_debug(format, args...)
L
Linus Torvalds 已提交
1348
/*
1349
  #define pr_debug printk
L
Linus Torvalds 已提交
1350 1351 1352 1353 1354 1355
*/
#endif
#define DEBUG_ARP_TABLE 0

#define LEC_ARP_REFRESH_INTERVAL (3*HZ)

D
David Howells 已提交
1356
static void lec_arp_check_expire(struct work_struct *work);
L
Linus Torvalds 已提交
1357 1358
static void lec_arp_expire_arp(unsigned long data);

1359
/*
L
Linus Torvalds 已提交
1360 1361 1362
 * Arp table funcs
 */

J
Joe Perches 已提交
1363
#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE - 1))
L
Linus Torvalds 已提交
1364 1365 1366 1367

/*
 * Initialization of arp-cache
 */
1368
static void lec_arp_init(struct lec_priv *priv)
L
Linus Torvalds 已提交
1369
{
1370
	unsigned short i;
L
Linus Torvalds 已提交
1371

J
Joe Perches 已提交
1372
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
1373
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1374 1375 1376
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
	INIT_HLIST_HEAD(&priv->lec_no_forward);
	INIT_HLIST_HEAD(&priv->mcast_fwds);
L
Linus Torvalds 已提交
1377
	spin_lock_init(&priv->lec_arp_lock);
D
David Howells 已提交
1378
	INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
1379
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
L
Linus Torvalds 已提交
1380 1381
}

1382
static void lec_arp_clear_vccs(struct lec_arp_table *entry)
L
Linus Torvalds 已提交
1383
{
1384
	if (entry->vcc) {
L
Linus Torvalds 已提交
1385 1386
		struct atm_vcc *vcc = entry->vcc;
		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
1387
		struct net_device *dev = (struct net_device *)vcc->proto_data;
L
Linus Torvalds 已提交
1388

1389
		vcc->pop = vpriv->old_pop;
L
Linus Torvalds 已提交
1390 1391 1392 1393
		if (vpriv->xoff)
			netif_wake_queue(dev);
		kfree(vpriv);
		vcc->user_back = NULL;
1394
		vcc->push = entry->old_push;
L
Linus Torvalds 已提交
1395
		vcc_release_async(vcc, -EPIPE);
1396
		entry->vcc = NULL;
1397 1398 1399
	}
	if (entry->recv_vcc) {
		entry->recv_vcc->push = entry->old_recv_push;
L
Linus Torvalds 已提交
1400
		vcc_release_async(entry->recv_vcc, -EPIPE);
1401 1402
		entry->recv_vcc = NULL;
	}
L
Linus Torvalds 已提交
1403 1404 1405 1406 1407 1408
}

/*
 * Insert entry to lec_arp_table
 * LANE2: Add to the end of the list to satisfy 8.1.13
 */
1409
static inline void
1410
lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
L
Linus Torvalds 已提交
1411
{
1412
	struct hlist_head *tmp;
1413

1414 1415
	tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
	hlist_add_head(&entry->next, tmp);
1416

1417
	pr_debug("Added entry:%pM\n", entry->mac_addr);
L
Linus Torvalds 已提交
1418 1419 1420 1421 1422
}

/*
 * Remove entry from lec_arp_table
 */
1423 1424
static int
lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
L
Linus Torvalds 已提交
1425
{
1426 1427 1428
	struct hlist_node *node;
	struct lec_arp_table *entry;
	int i, remove_vcc = 1;
1429

J
Joe Perches 已提交
1430
	if (!to_remove)
1431
		return -1;
1432 1433

	hlist_del(&to_remove->next);
1434 1435
	del_timer(&to_remove->timer);

J
Joe Perches 已提交
1436 1437 1438 1439
	/*
	 * If this is the only MAC connected to this VCC,
	 * also tear down the VCC
	 */
1440 1441 1442 1443
	if (to_remove->status >= ESI_FLUSH_PENDING) {
		/*
		 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
		 */
1444
		for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1445 1446
			hlist_for_each_entry(entry, node,
					     &priv->lec_arp_tables[i], next) {
1447 1448
				if (memcmp(to_remove->atm_addr,
					   entry->atm_addr, ATM_ESA_LEN) == 0) {
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
					remove_vcc = 0;
					break;
				}
			}
		}
		if (remove_vcc)
			lec_arp_clear_vccs(to_remove);
	}
	skb_queue_purge(&to_remove->tx_wait);	/* FIXME: good place for this? */

1459
	pr_debug("Removed entry:%pM\n", to_remove->mac_addr);
1460
	return 0;
L
Linus Torvalds 已提交
1461 1462 1463
}

#if DEBUG_ARP_TABLE
1464
static const char *get_status_string(unsigned char st)
L
Linus Torvalds 已提交
1465
{
1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
	switch (st) {
	case ESI_UNKNOWN:
		return "ESI_UNKNOWN";
	case ESI_ARP_PENDING:
		return "ESI_ARP_PENDING";
	case ESI_VC_PENDING:
		return "ESI_VC_PENDING";
	case ESI_FLUSH_PENDING:
		return "ESI_FLUSH_PENDING";
	case ESI_FORWARD_DIRECT:
		return "ESI_FORWARD_DIRECT";
	}
J
Joe Perches 已提交
1478
	return "<UNKNOWN>";
L
Linus Torvalds 已提交
1479 1480
}

1481
static void dump_arp_table(struct lec_priv *priv)
L
Linus Torvalds 已提交
1482
{
1483
	struct hlist_node *node;
1484
	struct lec_arp_table *rulla;
1485 1486
	char buf[256];
	int i, j, offset;
1487

J
Joe Perches 已提交
1488
	pr_info("Dump %p:\n", priv);
1489
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1490 1491
		hlist_for_each_entry(rulla, node,
				     &priv->lec_arp_tables[i], next) {
1492 1493
			offset = 0;
			offset += sprintf(buf, "%d: %p\n", i, rulla);
J
Joe Perches 已提交
1494 1495 1496
			offset += sprintf(buf + offset, "Mac: %pM",
					  rulla->mac_addr);
			offset += sprintf(buf + offset, " Atm:");
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
			for (j = 0; j < ATM_ESA_LEN; j++) {
				offset += sprintf(buf + offset,
						  "%2.2x ",
						  rulla->atm_addr[j] & 0xff);
			}
			offset += sprintf(buf + offset,
					  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
					  rulla->vcc ? rulla->vcc->vpi : 0,
					  rulla->vcc ? rulla->vcc->vci : 0,
					  rulla->recv_vcc ? rulla->recv_vcc->
					  vpi : 0,
					  rulla->recv_vcc ? rulla->recv_vcc->
					  vci : 0, rulla->last_used,
					  rulla->timestamp, rulla->no_tries);
			offset +=
			    sprintf(buf + offset,
				    "Flags:%x, Packets_flooded:%x, Status: %s ",
				    rulla->flags, rulla->packets_flooded,
				    get_status_string(rulla->status));
J
Joe Perches 已提交
1516
			pr_info("%s\n", buf);
1517 1518
		}
	}
1519 1520

	if (!hlist_empty(&priv->lec_no_forward))
J
Joe Perches 已提交
1521
		pr_info("No forward\n");
1522
	hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
1523
		offset = 0;
J
Joe Perches 已提交
1524 1525
		offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr);
		offset += sprintf(buf + offset, " Atm:");
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
		for (j = 0; j < ATM_ESA_LEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->atm_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset,
				  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
				  rulla->vcc ? rulla->vcc->vpi : 0,
				  rulla->vcc ? rulla->vcc->vci : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
				  rulla->last_used,
				  rulla->timestamp, rulla->no_tries);
		offset += sprintf(buf + offset,
				  "Flags:%x, Packets_flooded:%x, Status: %s ",
				  rulla->flags, rulla->packets_flooded,
				  get_status_string(rulla->status));
J
Joe Perches 已提交
1542
		pr_info("%s\n", buf);
1543
	}
1544 1545

	if (!hlist_empty(&priv->lec_arp_empty_ones))
J
Joe Perches 已提交
1546
		pr_info("Empty ones\n");
1547
	hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
1548
		offset = 0;
J
Joe Perches 已提交
1549 1550
		offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr);
		offset += sprintf(buf + offset, " Atm:");
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
		for (j = 0; j < ATM_ESA_LEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->atm_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset,
				  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
				  rulla->vcc ? rulla->vcc->vpi : 0,
				  rulla->vcc ? rulla->vcc->vci : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
				  rulla->last_used,
				  rulla->timestamp, rulla->no_tries);
		offset += sprintf(buf + offset,
				  "Flags:%x, Packets_flooded:%x, Status: %s ",
				  rulla->flags, rulla->packets_flooded,
				  get_status_string(rulla->status));
J
Joe Perches 已提交
1567
		pr_info("%s", buf);
1568 1569
	}

1570
	if (!hlist_empty(&priv->mcast_fwds))
J
Joe Perches 已提交
1571
		pr_info("Multicast Forward VCCs\n");
1572
	hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
1573
		offset = 0;
J
Joe Perches 已提交
1574 1575
		offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr);
		offset += sprintf(buf + offset, " Atm:");
1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
		for (j = 0; j < ATM_ESA_LEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->atm_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset,
				  "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
				  rulla->vcc ? rulla->vcc->vpi : 0,
				  rulla->vcc ? rulla->vcc->vci : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
				  rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
				  rulla->last_used,
				  rulla->timestamp, rulla->no_tries);
		offset += sprintf(buf + offset,
				  "Flags:%x, Packets_flooded:%x, Status: %s ",
				  rulla->flags, rulla->packets_flooded,
				  get_status_string(rulla->status));
J
Joe Perches 已提交
1592
		pr_info("%s\n", buf);
1593
	}
L
Linus Torvalds 已提交
1594 1595

}
1596 1597 1598
#else
#define dump_arp_table(priv) do { } while (0)
#endif
L
Linus Torvalds 已提交
1599 1600 1601 1602

/*
 * Destruction of arp-cache
 */
1603
static void lec_arp_destroy(struct lec_priv *priv)
L
Linus Torvalds 已提交
1604 1605
{
	unsigned long flags;
1606 1607
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1608 1609
	int i;

1610
	cancel_delayed_work_sync(&priv->lec_arp_work);
L
Linus Torvalds 已提交
1611

1612 1613 1614
	/*
	 * Remove all entries
	 */
L
Linus Torvalds 已提交
1615 1616

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1617
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1618 1619
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_tables[i], next) {
1620
			lec_arp_remove(priv, entry);
1621
			lec_arp_put(entry);
1622
		}
1623
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1624
	}
1625

J
Joe Perches 已提交
1626 1627
	hlist_for_each_entry_safe(entry, node, next,
				  &priv->lec_arp_empty_ones, next) {
1628 1629
		del_timer_sync(&entry->timer);
		lec_arp_clear_vccs(entry);
1630
		hlist_del(&entry->next);
1631
		lec_arp_put(entry);
1632
	}
1633 1634
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);

J
Joe Perches 已提交
1635 1636
	hlist_for_each_entry_safe(entry, node, next,
				  &priv->lec_no_forward, next) {
1637 1638
		del_timer_sync(&entry->timer);
		lec_arp_clear_vccs(entry);
1639
		hlist_del(&entry->next);
1640
		lec_arp_put(entry);
1641
	}
1642 1643 1644
	INIT_HLIST_HEAD(&priv->lec_no_forward);

	hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
1645 1646
		/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
		lec_arp_clear_vccs(entry);
1647
		hlist_del(&entry->next);
1648
		lec_arp_put(entry);
1649
	}
1650
	INIT_HLIST_HEAD(&priv->mcast_fwds);
1651
	priv->mcast_vcc = NULL;
L
Linus Torvalds 已提交
1652 1653 1654
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

1655
/*
L
Linus Torvalds 已提交
1656 1657
 * Find entry by mac_address
 */
1658
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
1659
					  const unsigned char *mac_addr)
L
Linus Torvalds 已提交
1660
{
1661 1662 1663
	struct hlist_node *node;
	struct hlist_head *head;
	struct lec_arp_table *entry;
1664

1665
	pr_debug("%pM\n", mac_addr);
1666

1667 1668
	head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
	hlist_for_each_entry(entry, node, head, next) {
J
Joe Perches 已提交
1669
		if (!compare_ether_addr(mac_addr, entry->mac_addr))
1670
			return entry;
1671 1672
	}
	return NULL;
L
Linus Torvalds 已提交
1673 1674
}

1675
static struct lec_arp_table *make_entry(struct lec_priv *priv,
1676
					const unsigned char *mac_addr)
L
Linus Torvalds 已提交
1677
{
1678 1679 1680 1681
	struct lec_arp_table *to_return;

	to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
	if (!to_return) {
J
Joe Perches 已提交
1682
		pr_info("LEC: Arp entry kmalloc failed\n");
1683 1684 1685
		return NULL;
	}
	memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
1686
	INIT_HLIST_NODE(&to_return->next);
1687 1688
	setup_timer(&to_return->timer, lec_arp_expire_arp,
			(unsigned long)to_return);
1689 1690 1691
	to_return->last_used = jiffies;
	to_return->priv = priv;
	skb_queue_head_init(&to_return->tx_wait);
1692
	atomic_set(&to_return->usage, 1);
1693
	return to_return;
L
Linus Torvalds 已提交
1694 1695
}

1696 1697
/* Arp sent timer expired */
static void lec_arp_expire_arp(unsigned long data)
L
Linus Torvalds 已提交
1698
{
1699 1700 1701 1702
	struct lec_arp_table *entry;

	entry = (struct lec_arp_table *)data;

1703
	pr_debug("\n");
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
	if (entry->status == ESI_ARP_PENDING) {
		if (entry->no_tries <= entry->priv->max_retry_count) {
			if (entry->is_rdesc)
				send_to_lecd(entry->priv, l_rdesc_arp_xmt,
					     entry->mac_addr, NULL, NULL);
			else
				send_to_lecd(entry->priv, l_arp_xmt,
					     entry->mac_addr, NULL, NULL);
			entry->no_tries++;
		}
		mod_timer(&entry->timer, jiffies + (1 * HZ));
	}
L
Linus Torvalds 已提交
1716 1717
}

1718 1719
/* Unknown/unused vcc expire, remove associated entry */
static void lec_arp_expire_vcc(unsigned long data)
L
Linus Torvalds 已提交
1720 1721
{
	unsigned long flags;
1722 1723
	struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
	struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
L
Linus Torvalds 已提交
1724

1725
	del_timer(&to_remove->timer);
L
Linus Torvalds 已提交
1726

1727 1728 1729 1730
	pr_debug("%p %p: vpi:%d vci:%d\n",
		 to_remove, priv,
		 to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
		 to_remove->vcc ? to_remove->recv_vcc->vci : 0);
L
Linus Torvalds 已提交
1731 1732

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1733
	hlist_del(&to_remove->next);
L
Linus Torvalds 已提交
1734 1735
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

1736
	lec_arp_clear_vccs(to_remove);
1737
	lec_arp_put(to_remove);
L
Linus Torvalds 已提交
1738 1739
}

1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783
static bool __lec_arp_check_expire(struct lec_arp_table *entry,
				   unsigned long now,
				   struct lec_priv *priv)
{
	unsigned long time_to_check;

	if ((entry->flags) & LEC_REMOTE_FLAG && priv->topology_change)
		time_to_check = priv->forward_delay_time;
	else
		time_to_check = priv->aging_time;

	pr_debug("About to expire: %lx - %lx > %lx\n",
		 now, entry->last_used, time_to_check);
	if (time_after(now, entry->last_used + time_to_check) &&
	    !(entry->flags & LEC_PERMANENT_FLAG) &&
	    !(entry->mac_addr[0] & 0x01)) {	/* LANE2: 7.1.20 */
		/* Remove entry */
		pr_debug("Entry timed out\n");
		lec_arp_remove(priv, entry);
		lec_arp_put(entry);
	} else {
		/* Something else */
		if ((entry->status == ESI_VC_PENDING ||
		     entry->status == ESI_ARP_PENDING) &&
		    time_after_eq(now, entry->timestamp +
				       priv->max_unknown_frame_time)) {
			entry->timestamp = jiffies;
			entry->packets_flooded = 0;
			if (entry->status == ESI_VC_PENDING)
				send_to_lecd(priv, l_svc_setup,
					     entry->mac_addr,
					     entry->atm_addr,
					     NULL);
		}
		if (entry->status == ESI_FLUSH_PENDING &&
		    time_after_eq(now, entry->timestamp +
				       priv->path_switching_delay)) {
			lec_arp_hold(entry);
			return true;
		}
	}

	return false;
}
L
Linus Torvalds 已提交
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
/*
 * Expire entries.
 * 1. Re-set timer
 * 2. For each entry, delete entries that have aged past the age limit.
 * 3. For each entry, depending on the status of the entry, perform
 *    the following maintenance.
 *    a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the
 *       tick_count is above the max_unknown_frame_time, clear
 *       the tick_count to zero and clear the packets_flooded counter
 *       to zero. This supports the packet rate limit per address
 *       while flooding unknowns.
 *    b. If the status is ESI_FLUSH_PENDING and the tick_count is greater
 *       than or equal to the path_switching_delay, change the status
 *       to ESI_FORWARD_DIRECT. This causes the flush period to end
 *       regardless of the progress of the flush protocol.
 */
D
David Howells 已提交
1800
static void lec_arp_check_expire(struct work_struct *work)
L
Linus Torvalds 已提交
1801 1802
{
	unsigned long flags;
D
David Howells 已提交
1803 1804
	struct lec_priv *priv =
		container_of(work, struct lec_priv, lec_arp_work.work);
1805 1806
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1807 1808 1809
	unsigned long now;
	int i;

1810
	pr_debug("%p\n", priv);
L
Linus Torvalds 已提交
1811
	now = jiffies;
1812
restart:
L
Linus Torvalds 已提交
1813
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1814
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1815 1816
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_tables[i], next) {
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826
			if (__lec_arp_check_expire(entry, now, priv)) {
				struct sk_buff *skb;
				struct atm_vcc *vcc = entry->vcc;

				spin_unlock_irqrestore(&priv->lec_arp_lock,
						       flags);
				while ((skb = skb_dequeue(&entry->tx_wait)))
					lec_send(vcc, skb);
				entry->last_used = jiffies;
				entry->status = ESI_FORWARD_DIRECT;
1827
				lec_arp_put(entry);
1828 1829

				goto restart;
L
Linus Torvalds 已提交
1830 1831 1832 1833 1834
			}
		}
	}
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

1835
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
L
Linus Torvalds 已提交
1836
}
1837

L
Linus Torvalds 已提交
1838 1839
/*
 * Try to find vcc where mac_address is attached.
1840
 *
L
Linus Torvalds 已提交
1841
 */
1842
static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
J
Joe Perches 已提交
1843 1844
				       const unsigned char *mac_to_find,
				       int is_rdesc,
1845
				       struct lec_arp_table **ret_entry)
L
Linus Torvalds 已提交
1846 1847
{
	unsigned long flags;
1848
	struct lec_arp_table *entry;
L
Linus Torvalds 已提交
1849 1850
	struct atm_vcc *found;

1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862
	if (mac_to_find[0] & 0x01) {
		switch (priv->lane_version) {
		case 1:
			return priv->mcast_vcc;
		case 2:	/* LANE2 wants arp for multicast addresses */
			if (!compare_ether_addr(mac_to_find, bus_mac))
				return priv->mcast_vcc;
			break;
		default:
			break;
		}
	}
L
Linus Torvalds 已提交
1863 1864

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1865 1866 1867 1868 1869 1870
	entry = lec_arp_find(priv, mac_to_find);

	if (entry) {
		if (entry->status == ESI_FORWARD_DIRECT) {
			/* Connection Ok */
			entry->last_used = jiffies;
1871
			lec_arp_hold(entry);
1872 1873
			*ret_entry = entry;
			found = entry->vcc;
L
Linus Torvalds 已提交
1874
			goto out;
1875 1876 1877
		}
		/*
		 * If the LE_ARP cache entry is still pending, reset count to 0
1878 1879
		 * so another LE_ARP request can be made for this frame.
		 */
J
Joe Perches 已提交
1880
		if (entry->status == ESI_ARP_PENDING)
1881
			entry->no_tries = 0;
1882 1883 1884 1885 1886 1887 1888 1889 1890 1891
		/*
		 * Data direct VC not yet set up, check to see if the unknown
		 * frame count is greater than the limit. If the limit has
		 * not been reached, allow the caller to send packet to
		 * BUS.
		 */
		if (entry->status != ESI_FLUSH_PENDING &&
		    entry->packets_flooded <
		    priv->maximum_unknown_frame_count) {
			entry->packets_flooded++;
1892
			pr_debug("Flooding..\n");
1893
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1894
			goto out;
1895 1896 1897
		}
		/*
		 * We got here because entry->status == ESI_FLUSH_PENDING
L
Linus Torvalds 已提交
1898 1899 1900
		 * or BUS flood limit was reached for an entry which is
		 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
		 */
1901
		lec_arp_hold(entry);
1902
		*ret_entry = entry;
1903 1904
		pr_debug("entry->status %d entry->vcc %p\n", entry->status,
			 entry->vcc);
1905 1906 1907 1908
		found = NULL;
	} else {
		/* No matching entry was found */
		entry = make_entry(priv, mac_to_find);
1909
		pr_debug("Making entry\n");
1910 1911
		if (!entry) {
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1912
			goto out;
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
		}
		lec_arp_add(priv, entry);
		/* We want arp-request(s) to be sent */
		entry->packets_flooded = 1;
		entry->status = ESI_ARP_PENDING;
		entry->no_tries = 1;
		entry->last_used = entry->timestamp = jiffies;
		entry->is_rdesc = is_rdesc;
		if (entry->is_rdesc)
			send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL,
				     NULL);
		else
			send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
		entry->timer.expires = jiffies + (1 * HZ);
		entry->timer.function = lec_arp_expire_arp;
		add_timer(&entry->timer);
		found = priv->mcast_vcc;
	}
L
Linus Torvalds 已提交
1931 1932 1933 1934 1935 1936 1937

out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
	return found;
}

static int
1938
lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr,
1939
		unsigned long permanent)
L
Linus Torvalds 已提交
1940 1941
{
	unsigned long flags;
1942 1943
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1944
	int i;
L
Linus Torvalds 已提交
1945

1946
	pr_debug("\n");
L
Linus Torvalds 已提交
1947
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1948
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1949 1950 1951 1952 1953
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_tables[i], next) {
			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) &&
			    (permanent ||
			     !(entry->flags & LEC_PERMANENT_FLAG))) {
L
Linus Torvalds 已提交
1954
				lec_arp_remove(priv, entry);
1955
				lec_arp_put(entry);
1956
			}
L
Linus Torvalds 已提交
1957
			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1958 1959 1960
			return 0;
		}
	}
L
Linus Torvalds 已提交
1961
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1962
	return -1;
L
Linus Torvalds 已提交
1963 1964 1965
}

/*
1966
 * Notifies:  Response to arp_request (atm_addr != NULL)
L
Linus Torvalds 已提交
1967 1968
 */
static void
1969 1970
lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
	       const unsigned char *atm_addr, unsigned long remoteflag,
1971
	       unsigned int targetless_le_arp)
L
Linus Torvalds 已提交
1972 1973
{
	unsigned long flags;
1974
	struct hlist_node *node, *next;
1975 1976
	struct lec_arp_table *entry, *tmp;
	int i;
L
Linus Torvalds 已提交
1977

1978 1979
	pr_debug("%smac:%pM\n",
		 (targetless_le_arp) ? "targetless " : "", mac_addr);
L
Linus Torvalds 已提交
1980 1981

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1982 1983 1984 1985 1986 1987
	entry = lec_arp_find(priv, mac_addr);
	if (entry == NULL && targetless_le_arp)
		goto out;	/*
				 * LANE2: ignore targetless LE_ARPs for which
				 * we have no entry in the cache. 7.1.30
				 */
1988
	if (!hlist_empty(&priv->lec_arp_empty_ones)) {
J
Joe Perches 已提交
1989 1990
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_empty_ones, next) {
1991 1992
			if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
				hlist_del(&entry->next);
1993
				del_timer(&entry->timer);
1994 1995 1996 1997 1998 1999 2000 2001 2002
				tmp = lec_arp_find(priv, mac_addr);
				if (tmp) {
					del_timer(&tmp->timer);
					tmp->status = ESI_FORWARD_DIRECT;
					memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
					tmp->vcc = entry->vcc;
					tmp->old_push = entry->old_push;
					tmp->last_used = jiffies;
					del_timer(&entry->timer);
2003
					lec_arp_put(entry);
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
					entry = tmp;
				} else {
					entry->status = ESI_FORWARD_DIRECT;
					memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
					entry->last_used = jiffies;
					lec_arp_add(priv, entry);
				}
				if (remoteflag)
					entry->flags |= LEC_REMOTE_FLAG;
				else
					entry->flags &= ~LEC_REMOTE_FLAG;
2015
				pr_debug("After update\n");
2016 2017
				dump_arp_table(priv);
				goto out;
2018 2019 2020
			}
		}
	}
2021

2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
	entry = lec_arp_find(priv, mac_addr);
	if (!entry) {
		entry = make_entry(priv, mac_addr);
		if (!entry)
			goto out;
		entry->status = ESI_UNKNOWN;
		lec_arp_add(priv, entry);
		/* Temporary, changes before end of function */
	}
	memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
	del_timer(&entry->timer);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
2034 2035
		hlist_for_each_entry(tmp, node,
				     &priv->lec_arp_tables[i], next) {
2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057
			if (entry != tmp &&
			    !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
				/* Vcc to this host exists */
				if (tmp->status > ESI_VC_PENDING) {
					/*
					 * ESI_FLUSH_PENDING,
					 * ESI_FORWARD_DIRECT
					 */
					entry->vcc = tmp->vcc;
					entry->old_push = tmp->old_push;
				}
				entry->status = tmp->status;
				break;
			}
		}
	}
	if (remoteflag)
		entry->flags |= LEC_REMOTE_FLAG;
	else
		entry->flags &= ~LEC_REMOTE_FLAG;
	if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
		entry->status = ESI_VC_PENDING;
2058
		send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
2059
	}
2060
	pr_debug("After update2\n");
2061
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2062 2063 2064 2065 2066
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

/*
2067
 * Notifies: Vcc setup ready
L
Linus Torvalds 已提交
2068 2069
 */
static void
2070
lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data,
2071 2072
	      struct atm_vcc *vcc,
	      void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
L
Linus Torvalds 已提交
2073 2074
{
	unsigned long flags;
2075
	struct hlist_node *node;
2076 2077
	struct lec_arp_table *entry;
	int i, found_entry = 0;
L
Linus Torvalds 已提交
2078 2079

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
J
Joe Perches 已提交
2080
	/* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
2081
	if (ioc_data->receive == 2) {
2082
		pr_debug("LEC_ARP: Attaching mcast forward\n");
L
Linus Torvalds 已提交
2083
#if 0
2084 2085
		entry = lec_arp_find(priv, bus_mac);
		if (!entry) {
J
Joe Perches 已提交
2086
			pr_info("LEC_ARP: Multicast entry not found!\n");
L
Linus Torvalds 已提交
2087
			goto out;
2088 2089 2090 2091
		}
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
L
Linus Torvalds 已提交
2092
#endif
2093 2094
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2095
			goto out;
2096 2097 2098 2099
		del_timer(&entry->timer);
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
2100
		hlist_add_head(&entry->next, &priv->mcast_fwds);
2101 2102 2103 2104 2105 2106
		goto out;
	} else if (ioc_data->receive == 1) {
		/*
		 * Vcc which we don't want to make default vcc,
		 * attach it anyway.
		 */
2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117
		pr_debug("LEC_ARP:Attaching data direct, not default: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
			 ioc_data->atm_addr[0], ioc_data->atm_addr[1],
			 ioc_data->atm_addr[2], ioc_data->atm_addr[3],
			 ioc_data->atm_addr[4], ioc_data->atm_addr[5],
			 ioc_data->atm_addr[6], ioc_data->atm_addr[7],
			 ioc_data->atm_addr[8], ioc_data->atm_addr[9],
			 ioc_data->atm_addr[10], ioc_data->atm_addr[11],
			 ioc_data->atm_addr[12], ioc_data->atm_addr[13],
			 ioc_data->atm_addr[14], ioc_data->atm_addr[15],
			 ioc_data->atm_addr[16], ioc_data->atm_addr[17],
			 ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
2118 2119
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2120
			goto out;
2121 2122 2123 2124 2125 2126 2127
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		memset(entry->mac_addr, 0, ETH_ALEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
		entry->status = ESI_UNKNOWN;
		entry->timer.expires = jiffies + priv->vcc_timeout_period;
		entry->timer.function = lec_arp_expire_vcc;
2128
		hlist_add_head(&entry->next, &priv->lec_no_forward);
2129
		add_timer(&entry->timer);
L
Linus Torvalds 已提交
2130 2131
		dump_arp_table(priv);
		goto out;
2132
	}
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
	pr_debug("LEC_ARP:Attaching data direct, default: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
		 ioc_data->atm_addr[0], ioc_data->atm_addr[1],
		 ioc_data->atm_addr[2], ioc_data->atm_addr[3],
		 ioc_data->atm_addr[4], ioc_data->atm_addr[5],
		 ioc_data->atm_addr[6], ioc_data->atm_addr[7],
		 ioc_data->atm_addr[8], ioc_data->atm_addr[9],
		 ioc_data->atm_addr[10], ioc_data->atm_addr[11],
		 ioc_data->atm_addr[12], ioc_data->atm_addr[13],
		 ioc_data->atm_addr[14], ioc_data->atm_addr[15],
		 ioc_data->atm_addr[16], ioc_data->atm_addr[17],
		 ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
2144
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
2145 2146
		hlist_for_each_entry(entry, node,
				     &priv->lec_arp_tables[i], next) {
2147 2148 2149
			if (memcmp
			    (ioc_data->atm_addr, entry->atm_addr,
			     ATM_ESA_LEN) == 0) {
2150 2151
				pr_debug("LEC_ARP: Attaching data direct\n");
				pr_debug("Currently -> Vcc: %d, Rvcc:%d\n",
2152 2153 2154
					 entry->vcc ? entry->vcc->vci : 0,
					 entry->recv_vcc ? entry->recv_vcc->
					 vci : 0);
2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
				found_entry = 1;
				del_timer(&entry->timer);
				entry->vcc = vcc;
				entry->old_push = old_push;
				if (entry->status == ESI_VC_PENDING) {
					if (priv->maximum_unknown_frame_count
					    == 0)
						entry->status =
						    ESI_FORWARD_DIRECT;
					else {
						entry->timestamp = jiffies;
						entry->status =
						    ESI_FLUSH_PENDING;
L
Linus Torvalds 已提交
2168
#if 0
2169 2170 2171 2172
						send_to_lecd(priv, l_flush_xmt,
							     NULL,
							     entry->atm_addr,
							     NULL);
L
Linus Torvalds 已提交
2173
#endif
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
					}
				} else {
					/*
					 * They were forming a connection
					 * to us, and we to them. Our
					 * ATM address is numerically lower
					 * than theirs, so we make connection
					 * we formed into default VCC (8.1.11).
					 * Connection they made gets torn
					 * down. This might confuse some
					 * clients. Can be changed if
					 * someone reports trouble...
					 */
					;
				}
			}
		}
	}
	if (found_entry) {
2193
		pr_debug("After vcc was added\n");
2194
		dump_arp_table(priv);
L
Linus Torvalds 已提交
2195
		goto out;
2196 2197 2198 2199 2200 2201 2202
	}
	/*
	 * Not found, snatch address from first data packet that arrives
	 * from this vcc
	 */
	entry = make_entry(priv, bus_mac);
	if (!entry)
L
Linus Torvalds 已提交
2203
		goto out;
2204 2205 2206 2207 2208
	entry->vcc = vcc;
	entry->old_push = old_push;
	memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
	memset(entry->mac_addr, 0, ETH_ALEN);
	entry->status = ESI_UNKNOWN;
2209
	hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
2210 2211 2212
	entry->timer.expires = jiffies + priv->vcc_timeout_period;
	entry->timer.function = lec_arp_expire_vcc;
	add_timer(&entry->timer);
2213
	pr_debug("After vcc was added\n");
L
Linus Torvalds 已提交
2214 2215 2216 2217 2218
	dump_arp_table(priv);
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

2219
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
L
Linus Torvalds 已提交
2220 2221
{
	unsigned long flags;
2222
	struct hlist_node *node;
2223 2224
	struct lec_arp_table *entry;
	int i;
L
Linus Torvalds 已提交
2225

2226
	pr_debug("%lx\n", tran_id);
2227
restart:
2228 2229
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
2230 2231 2232 2233
		hlist_for_each_entry(entry, node,
				     &priv->lec_arp_tables[i], next) {
			if (entry->flush_tran_id == tran_id &&
			    entry->status == ESI_FLUSH_PENDING) {
2234
				struct sk_buff *skb;
2235
				struct atm_vcc *vcc = entry->vcc;
2236

2237
				lec_arp_hold(entry);
J
Joe Perches 已提交
2238 2239
				spin_unlock_irqrestore(&priv->lec_arp_lock,
						       flags);
2240
				while ((skb = skb_dequeue(&entry->tx_wait)))
2241
					lec_send(vcc, skb);
2242
				entry->last_used = jiffies;
2243
				entry->status = ESI_FORWARD_DIRECT;
2244
				lec_arp_put(entry);
2245
				pr_debug("LEC_ARP: Flushed\n");
2246
				goto restart;
2247 2248 2249
			}
		}
	}
L
Linus Torvalds 已提交
2250
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2251
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2252 2253 2254 2255
}

static void
lec_set_flush_tran_id(struct lec_priv *priv,
2256
		      const unsigned char *atm_addr, unsigned long tran_id)
L
Linus Torvalds 已提交
2257 2258
{
	unsigned long flags;
2259
	struct hlist_node *node;
2260 2261
	struct lec_arp_table *entry;
	int i;
L
Linus Torvalds 已提交
2262 2263

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2264
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
J
Joe Perches 已提交
2265 2266
		hlist_for_each_entry(entry, node,
				     &priv->lec_arp_tables[i], next) {
2267 2268
			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
				entry->flush_tran_id = tran_id;
2269
				pr_debug("Set flush transaction id to %lx for %p\n",
2270
					 tran_id, entry);
2271
			}
2272
		}
L
Linus Torvalds 已提交
2273 2274 2275
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

2276
static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
L
Linus Torvalds 已提交
2277 2278
{
	unsigned long flags;
2279 2280 2281 2282
	unsigned char mac_addr[] = {
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
	};
	struct lec_arp_table *to_add;
L
Linus Torvalds 已提交
2283 2284
	struct lec_vcc_priv *vpriv;
	int err = 0;
2285

J
Joe Perches 已提交
2286 2287
	vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
	if (!vpriv)
L
Linus Torvalds 已提交
2288 2289 2290 2291
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
2292
	vcc->pop = lec_pop;
L
Linus Torvalds 已提交
2293
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2294 2295
	to_add = make_entry(priv, mac_addr);
	if (!to_add) {
L
Linus Torvalds 已提交
2296 2297
		vcc->pop = vpriv->old_pop;
		kfree(vpriv);
2298
		err = -ENOMEM;
L
Linus Torvalds 已提交
2299
		goto out;
2300 2301 2302 2303 2304 2305 2306 2307 2308
	}
	memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
	to_add->status = ESI_FORWARD_DIRECT;
	to_add->flags |= LEC_PERMANENT_FLAG;
	to_add->vcc = vcc;
	to_add->old_push = vcc->push;
	vcc->push = lec_push;
	priv->mcast_vcc = vcc;
	lec_arp_add(priv, to_add);
L
Linus Torvalds 已提交
2309 2310
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2311
	return err;
L
Linus Torvalds 已提交
2312 2313
}

2314
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
L
Linus Torvalds 已提交
2315 2316
{
	unsigned long flags;
2317 2318
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
2319
	int i;
L
Linus Torvalds 已提交
2320

2321
	pr_debug("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
2322
	dump_arp_table(priv);
2323

L
Linus Torvalds 已提交
2324
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2325

2326
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
2327 2328
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_tables[i], next) {
2329 2330
			if (vcc == entry->vcc) {
				lec_arp_remove(priv, entry);
2331
				lec_arp_put(entry);
J
Joe Perches 已提交
2332
				if (priv->mcast_vcc == vcc)
2333 2334 2335 2336 2337
					priv->mcast_vcc = NULL;
			}
		}
	}

J
Joe Perches 已提交
2338 2339
	hlist_for_each_entry_safe(entry, node, next,
				  &priv->lec_arp_empty_ones, next) {
2340
		if (entry->vcc == vcc) {
2341 2342
			lec_arp_clear_vccs(entry);
			del_timer(&entry->timer);
2343
			hlist_del(&entry->next);
2344
			lec_arp_put(entry);
2345 2346 2347
		}
	}

J
Joe Perches 已提交
2348 2349
	hlist_for_each_entry_safe(entry, node, next,
				  &priv->lec_no_forward, next) {
2350 2351 2352
		if (entry->recv_vcc == vcc) {
			lec_arp_clear_vccs(entry);
			del_timer(&entry->timer);
2353
			hlist_del(&entry->next);
2354
			lec_arp_put(entry);
2355 2356 2357
		}
	}

2358
	hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
2359 2360 2361
		if (entry->recv_vcc == vcc) {
			lec_arp_clear_vccs(entry);
			/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
2362
			hlist_del(&entry->next);
2363
			lec_arp_put(entry);
2364 2365
		}
	}
L
Linus Torvalds 已提交
2366 2367 2368 2369 2370 2371 2372

	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
	dump_arp_table(priv);
}

static void
lec_arp_check_empties(struct lec_priv *priv,
2373
		      struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
2374
{
2375
	unsigned long flags;
2376 2377
	struct hlist_node *node, *next;
	struct lec_arp_table *entry, *tmp;
2378 2379
	struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
	unsigned char *src;
L
Linus Torvalds 已提交
2380
#ifdef CONFIG_TR
2381
	struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
L
Linus Torvalds 已提交
2382

2383 2384 2385
	if (priv->is_trdev)
		src = tr_hdr->h_source;
	else
L
Linus Torvalds 已提交
2386
#endif
2387
		src = hdr->h_source;
L
Linus Torvalds 已提交
2388 2389

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
J
Joe Perches 已提交
2390 2391
	hlist_for_each_entry_safe(entry, node, next,
				  &priv->lec_arp_empty_ones, next) {
2392 2393 2394 2395 2396 2397
		if (vcc == entry->vcc) {
			del_timer(&entry->timer);
			memcpy(entry->mac_addr, src, ETH_ALEN);
			entry->status = ESI_FORWARD_DIRECT;
			entry->last_used = jiffies;
			/* We might have got an entry */
J
Joe Perches 已提交
2398 2399
			tmp = lec_arp_find(priv, src);
			if (tmp) {
2400
				lec_arp_remove(priv, tmp);
2401
				lec_arp_put(tmp);
2402 2403 2404 2405
			}
			hlist_del(&entry->next);
			lec_arp_add(priv, entry);
			goto out;
2406 2407
		}
	}
2408
	pr_debug("LEC_ARP: Arp_check_empties: entry not found!\n");
L
Linus Torvalds 已提交
2409 2410 2411
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
2412

L
Linus Torvalds 已提交
2413
MODULE_LICENSE("GPL");