lec.c 63.5 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 820
	return lec_mcast_make((struct lec_priv *)netdev_priv(dev_lec[arg]),
				vcc);
L
Linus Torvalds 已提交
821 822 823
}

/* Initialize device. */
824 825 826 827 828 829 830 831 832
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 已提交
833
#ifdef CONFIG_TR
834 835 836 837 838
	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 已提交
839
#endif
840 841
	if (!dev_lec[i]) {
		int is_trdev, size;
L
Linus Torvalds 已提交
842

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

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

863
		priv = netdev_priv(dev_lec[i]);
864 865
		priv->is_trdev = is_trdev;
	} else {
866
		priv = netdev_priv(dev_lec[i]);
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
		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 已提交
892
	if (dev_lec[i]->flags & IFF_UP)
893 894 895
		netif_start_queue(dev_lec[i]);
	__module_get(THIS_MODULE);
	return i;
L
Linus Torvalds 已提交
896 897 898
}

#ifdef CONFIG_PROC_FS
899
static const char *lec_arp_get_status_string(unsigned char status)
L
Linus Torvalds 已提交
900
{
901
	static const char *const lec_arp_status_string[] = {
L
Linus Torvalds 已提交
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 928
		"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
929
		seq_printf(seq, "        ");
L
Linus Torvalds 已提交
930 931 932
	if (entry->recv_vcc) {
		seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,
			   entry->recv_vcc->vci);
933 934
	}
	seq_putc(seq, '\n');
L
Linus Torvalds 已提交
935 936 937 938 939
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return err;
}

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

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

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

	register_atm_ioctl(&lane_ioctl_ops);
J
Joe Perches 已提交
1177
	pr_info("lec.c: " __DATE__ " " __TIME__ " initialized\n");
1178
	return 0;
L
Linus Torvalds 已提交
1179 1180 1181 1182
}

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

	remove_proc_entry("lec", atm_proc_root);

	deregister_atm_ioctl(&lane_ioctl_ops);

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

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

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

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

		*sizeoftlvs = table->sizeoftlvs;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#define LEC_ARP_REFRESH_INTERVAL (3*HZ)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#if DEBUG_ARP_TABLE
1465
static const char *get_status_string(unsigned char st)
L
Linus Torvalds 已提交
1466
{
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478
	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 已提交
1479
	return "<UNKNOWN>";
L
Linus Torvalds 已提交
1480 1481
}

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

J
Joe Perches 已提交
1489
	pr_info("Dump %p:\n", priv);
1490
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1491 1492
		hlist_for_each_entry(rulla, node,
				     &priv->lec_arp_tables[i], next) {
1493 1494
			offset = 0;
			offset += sprintf(buf, "%d: %p\n", i, rulla);
J
Joe Perches 已提交
1495 1496 1497
			offset += sprintf(buf + offset, "Mac: %pM",
					  rulla->mac_addr);
			offset += sprintf(buf + offset, " Atm:");
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516
			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 已提交
1517
			pr_info("%s\n", buf);
1518 1519
		}
	}
1520 1521

	if (!hlist_empty(&priv->lec_no_forward))
J
Joe Perches 已提交
1522
		pr_info("No forward\n");
1523
	hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
1524
		offset = 0;
J
Joe Perches 已提交
1525 1526
		offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr);
		offset += sprintf(buf + offset, " Atm:");
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
		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 已提交
1543
		pr_info("%s\n", buf);
1544
	}
1545 1546

	if (!hlist_empty(&priv->lec_arp_empty_ones))
J
Joe Perches 已提交
1547
		pr_info("Empty ones\n");
1548
	hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
1549
		offset = 0;
J
Joe Perches 已提交
1550 1551
		offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr);
		offset += sprintf(buf + offset, " Atm:");
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
		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 已提交
1568
		pr_info("%s", buf);
1569 1570
	}

1571
	if (!hlist_empty(&priv->mcast_fwds))
J
Joe Perches 已提交
1572
		pr_info("Multicast Forward VCCs\n");
1573
	hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
1574
		offset = 0;
J
Joe Perches 已提交
1575 1576
		offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr);
		offset += sprintf(buf + offset, " Atm:");
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
		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 已提交
1593
		pr_info("%s\n", buf);
1594
	}
L
Linus Torvalds 已提交
1595 1596

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

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

1611
	cancel_rearming_delayed_work(&priv->lec_arp_work);
L
Linus Torvalds 已提交
1612

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

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

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

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

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

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

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

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

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

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

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

	entry = (struct lec_arp_table *)data;

1704
	pr_debug("\n");
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
	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 已提交
1717 1718
}

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

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

1728 1729 1730 1731
	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 已提交
1732 1733

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

1737
	lec_arp_clear_vccs(to_remove);
1738
	lec_arp_put(to_remove);
L
Linus Torvalds 已提交
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 1784
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 已提交
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
/*
 * 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 已提交
1801
static void lec_arp_check_expire(struct work_struct *work)
L
Linus Torvalds 已提交
1802 1803
{
	unsigned long flags;
D
David Howells 已提交
1804 1805
	struct lec_priv *priv =
		container_of(work, struct lec_priv, lec_arp_work.work);
1806 1807
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1808 1809 1810
	unsigned long now;
	int i;

1811
	pr_debug("%p\n", priv);
L
Linus Torvalds 已提交
1812
	now = jiffies;
1813
restart:
L
Linus Torvalds 已提交
1814
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1815
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1816 1817
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_tables[i], next) {
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
			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;
1828
				lec_arp_put(entry);
1829 1830

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

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

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

1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863
	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 已提交
1864 1865

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

	if (entry) {
		if (entry->status == ESI_FORWARD_DIRECT) {
			/* Connection Ok */
			entry->last_used = jiffies;
1872
			lec_arp_hold(entry);
1873 1874
			*ret_entry = entry;
			found = entry->vcc;
L
Linus Torvalds 已提交
1875
			goto out;
1876 1877 1878
		}
		/*
		 * If the LE_ARP cache entry is still pending, reset count to 0
1879 1880
		 * so another LE_ARP request can be made for this frame.
		 */
J
Joe Perches 已提交
1881
		if (entry->status == ESI_ARP_PENDING)
1882
			entry->no_tries = 0;
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
		/*
		 * 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++;
1893
			pr_debug("Flooding..\n");
1894
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1895
			goto out;
1896 1897 1898
		}
		/*
		 * We got here because entry->status == ESI_FLUSH_PENDING
L
Linus Torvalds 已提交
1899 1900 1901
		 * or BUS flood limit was reached for an entry which is
		 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
		 */
1902
		lec_arp_hold(entry);
1903
		*ret_entry = entry;
1904 1905
		pr_debug("entry->status %d entry->vcc %p\n", entry->status,
			 entry->vcc);
1906 1907 1908 1909
		found = NULL;
	} else {
		/* No matching entry was found */
		entry = make_entry(priv, mac_to_find);
1910
		pr_debug("Making entry\n");
1911 1912
		if (!entry) {
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1913
			goto out;
1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
		}
		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 已提交
1932 1933 1934 1935 1936 1937 1938

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

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

1947
	pr_debug("\n");
L
Linus Torvalds 已提交
1948
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1949
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
1950 1951 1952 1953 1954
		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 已提交
1955
				lec_arp_remove(priv, entry);
1956
				lec_arp_put(entry);
1957
			}
L
Linus Torvalds 已提交
1958
			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1959 1960 1961
			return 0;
		}
	}
L
Linus Torvalds 已提交
1962
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1963
	return -1;
L
Linus Torvalds 已提交
1964 1965 1966
}

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

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

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1983 1984 1985 1986 1987 1988
	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
				 */
1989
	if (!hlist_empty(&priv->lec_arp_empty_ones)) {
J
Joe Perches 已提交
1990 1991
		hlist_for_each_entry_safe(entry, node, next,
					  &priv->lec_arp_empty_ones, next) {
1992 1993
			if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
				hlist_del(&entry->next);
1994
				del_timer(&entry->timer);
1995 1996 1997 1998 1999 2000 2001 2002 2003
				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);
2004
					lec_arp_put(entry);
2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015
					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;
2016
				pr_debug("After update\n");
2017 2018
				dump_arp_table(priv);
				goto out;
2019 2020 2021
			}
		}
	}
2022

2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034
	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 已提交
2035 2036
		hlist_for_each_entry(tmp, node,
				     &priv->lec_arp_tables[i], next) {
2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
			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;
2059
		send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
2060
	}
2061
	pr_debug("After update2\n");
2062
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2063 2064 2065 2066 2067
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

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

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
J
Joe Perches 已提交
2081
	/* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
2082
	if (ioc_data->receive == 2) {
2083
		pr_debug("LEC_ARP: Attaching mcast forward\n");
L
Linus Torvalds 已提交
2084
#if 0
2085 2086
		entry = lec_arp_find(priv, bus_mac);
		if (!entry) {
J
Joe Perches 已提交
2087
			pr_info("LEC_ARP: Multicast entry not found!\n");
L
Linus Torvalds 已提交
2088
			goto out;
2089 2090 2091 2092
		}
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
L
Linus Torvalds 已提交
2093
#endif
2094 2095
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2096
			goto out;
2097 2098 2099 2100
		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;
2101
		hlist_add_head(&entry->next, &priv->mcast_fwds);
2102 2103 2104 2105 2106 2107
		goto out;
	} else if (ioc_data->receive == 1) {
		/*
		 * Vcc which we don't want to make default vcc,
		 * attach it anyway.
		 */
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
		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]);
2119 2120
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2121
			goto out;
2122 2123 2124 2125 2126 2127 2128
		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;
2129
		hlist_add_head(&entry->next, &priv->lec_no_forward);
2130
		add_timer(&entry->timer);
L
Linus Torvalds 已提交
2131 2132
		dump_arp_table(priv);
		goto out;
2133
	}
2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
	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]);
2145
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
J
Joe Perches 已提交
2146 2147
		hlist_for_each_entry(entry, node,
				     &priv->lec_arp_tables[i], next) {
2148 2149 2150
			if (memcmp
			    (ioc_data->atm_addr, entry->atm_addr,
			     ATM_ESA_LEN) == 0) {
2151 2152
				pr_debug("LEC_ARP: Attaching data direct\n");
				pr_debug("Currently -> Vcc: %d, Rvcc:%d\n",
2153 2154 2155
					 entry->vcc ? entry->vcc->vci : 0,
					 entry->recv_vcc ? entry->recv_vcc->
					 vci : 0);
2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
				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 已提交
2169
#if 0
2170 2171 2172 2173
						send_to_lecd(priv, l_flush_xmt,
							     NULL,
							     entry->atm_addr,
							     NULL);
L
Linus Torvalds 已提交
2174
#endif
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193
					}
				} 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) {
2194
		pr_debug("After vcc was added\n");
2195
		dump_arp_table(priv);
L
Linus Torvalds 已提交
2196
		goto out;
2197 2198 2199 2200 2201 2202 2203
	}
	/*
	 * Not found, snatch address from first data packet that arrives
	 * from this vcc
	 */
	entry = make_entry(priv, bus_mac);
	if (!entry)
L
Linus Torvalds 已提交
2204
		goto out;
2205 2206 2207 2208 2209
	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;
2210
	hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
2211 2212 2213
	entry->timer.expires = jiffies + priv->vcc_timeout_period;
	entry->timer.function = lec_arp_expire_vcc;
	add_timer(&entry->timer);
2214
	pr_debug("After vcc was added\n");
L
Linus Torvalds 已提交
2215 2216 2217 2218 2219
	dump_arp_table(priv);
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

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

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

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

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

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

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

J
Joe Perches 已提交
2287 2288
	vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
	if (!vpriv)
L
Linus Torvalds 已提交
2289 2290 2291 2292
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
2293
	vcc->pop = lec_pop;
L
Linus Torvalds 已提交
2294
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2295 2296
	to_add = make_entry(priv, mac_addr);
	if (!to_add) {
L
Linus Torvalds 已提交
2297 2298
		vcc->pop = vpriv->old_pop;
		kfree(vpriv);
2299
		err = -ENOMEM;
L
Linus Torvalds 已提交
2300
		goto out;
2301 2302 2303 2304 2305 2306 2307 2308 2309
	}
	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 已提交
2310 2311
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2312
	return err;
L
Linus Torvalds 已提交
2313 2314
}

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

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

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

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

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

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

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

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

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

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

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
J
Joe Perches 已提交
2391 2392
	hlist_for_each_entry_safe(entry, node, next,
				  &priv->lec_arp_empty_ones, next) {
2393 2394 2395 2396 2397 2398
		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 已提交
2399 2400
			tmp = lec_arp_find(priv, src);
			if (tmp) {
2401
				lec_arp_remove(priv, tmp);
2402
				lec_arp_put(tmp);
2403 2404 2405 2406
			}
			hlist_del(&entry->next);
			lec_arp_add(priv, entry);
			goto out;
2407 2408
		}
	}
2409
	pr_debug("LEC_ARP: Arp_check_empties: entry not found!\n");
L
Linus Torvalds 已提交
2410 2411 2412
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
2413

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