lec.c 65.3 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
 */

#include <linux/kernel.h>
#include <linux/bitops.h>
9
#include <linux/capability.h>
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

/* 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>
#include <asm/uaccess.h>
#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"

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

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

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

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

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

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

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

101 102 103 104 105 106 107 108 109 110 111 112 113
/* 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 已提交
114
static struct lane2_ops lane2_ops = {
115 116 117
	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 已提交
118 119
};

120
static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
L
Linus Torvalds 已提交
121 122 123 124 125 126 127

/* 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)
{
128 129 130 131 132 133 134 135 136 137 138 139
	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 已提交
140
		struct sock *sk;
141 142 143 144 145 146 147 148 149 150 151 152
		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;
		mesg->content.normal.flag = *buff & 0x01;	/* 0x01 is topology change */

153
		priv = netdev_priv(dev);
154
		atm_force_charge(priv->lecd, skb2->truesize);
L
Linus Torvalds 已提交
155
		sk = sk_atm(priv->lecd);
156 157 158
		skb_queue_tail(&sk->sk_receive_queue, skb2);
		sk->sk_data_ready(sk, skb2->len);
	}
L
Linus Torvalds 已提交
159

160
	return;
L
Linus Torvalds 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
}
#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)
{
176
	struct trh_hdr *trh;
177
	unsigned int riflen, num_rdsc;
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

	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 已提交
198
		memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(__be16));
199
	else {
A
Al Viro 已提交
200
		memcpy(&rdesc[4], &trh->rseg[1], sizeof(__be16));
201 202 203 204
		rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
	}

	return NULL;
L
Linus Torvalds 已提交
205 206 207 208 209 210 211 212 213 214 215 216
}
#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.
 */

217
static int lec_open(struct net_device *dev)
L
Linus Torvalds 已提交
218 219
{
	netif_start_queue(dev);
220
	memset(&dev->stats, 0, sizeof(struct net_device_stats));
221 222

	return 0;
L
Linus Torvalds 已提交
223 224
}

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

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

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

243
static void lec_tx_timeout(struct net_device *dev)
L
Linus Torvalds 已提交
244 245 246 247 248 249
{
	printk(KERN_INFO "%s: tx timeout\n", dev->name);
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}

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

268
	pr_debug("lec_start_xmit called\n");
269 270
	if (!priv->lecd) {
		printk("%s:No lecd attached\n", dev->name);
271
		dev->stats.tx_errors++;
272
		netif_stop_queue(dev);
273 274
		kfree_skb(skb);
		return NETDEV_TX_OK;
275 276
	}

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

285 286
	/* Make sure we have room for lec_id */
	if (skb_headroom(skb) < 2) {
L
Linus Torvalds 已提交
287

288
		pr_debug("lec_start_xmit: reallocating skb\n");
289 290 291
		skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
		kfree_skb(skb);
		if (skb2 == NULL)
292
			return NETDEV_TX_OK;
293 294 295
		skb = skb2;
	}
	skb_push(skb, 2);
L
Linus Torvalds 已提交
296

297 298 299
	/* 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 已提交
300 301

#ifdef CONFIG_TR
302 303 304 305 306 307 308 309
	/*
	 * 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)
310
			return NETDEV_TX_OK;
311 312
		skb = skb2;
	}
L
Linus Torvalds 已提交
313 314 315
#endif

#if DUMP_PACKETS > 0
316 317
	printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
	       skb->len, priv->lecid);
L
Linus Torvalds 已提交
318
#if DUMP_PACKETS >= 2
319 320 321
	for (i = 0; i < skb->len && i < 99; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
322
#elif DUMP_PACKETS >= 1
323 324 325
	for (i = 0; i < skb->len && i < 30; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
326
#endif /* DUMP_PACKETS >= 1 */
327 328 329 330
	if (i == skb->len)
		printk("%s\n", buf);
	else
		printk("%s...\n", buf);
L
Linus Torvalds 已提交
331 332
#endif /* DUMP_PACKETS > 0 */

333
	/* Minimum ethernet-frame size */
L
Linus Torvalds 已提交
334
#ifdef CONFIG_TR
335 336
	if (priv->is_trdev)
		min_frame_size = LEC_MINIMUM_8025_SIZE;
L
Linus Torvalds 已提交
337 338
	else
#endif
339 340 341 342 343 344 345 346
		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) {
347
				dev->stats.tx_dropped++;
348
				return NETDEV_TX_OK;
349 350 351
			}
			skb = skb2;
		}
L
Linus Torvalds 已提交
352
		skb_put(skb, min_frame_size - skb->len);
353 354 355 356 357
	}

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

	while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
392
		pr_debug("lec.c: emptying tx queue, ");
J
Johannes Berg 已提交
393
		pr_debug("MAC address %pM\n", lec_h->h_dest);
394
		lec_send(vcc, skb2);
395
	}
L
Linus Torvalds 已提交
396

397
	lec_send(vcc, skb);
L
Linus Torvalds 已提交
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414

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

415 416 417
out:
	if (entry)
		lec_arp_put(entry);
L
Linus Torvalds 已提交
418
	dev->trans_start = jiffies;
419
	return NETDEV_TX_OK;
L
Linus Torvalds 已提交
420 421 422
}

/* The inverse routine to net_open(). */
423
static int lec_close(struct net_device *dev)
L
Linus Torvalds 已提交
424
{
425 426
	netif_stop_queue(dev);
	return 0;
L
Linus Torvalds 已提交
427 428
}

429
static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
430 431
{
	unsigned long flags;
432
	struct net_device *dev = (struct net_device *)vcc->proto_data;
433
	struct lec_priv *priv = netdev_priv(dev);
434 435 436 437
	struct atmlec_msg *mesg;
	struct lec_arp_table *entry;
	int i;
	char *tmp;		/* FIXME */
L
Linus Torvalds 已提交
438 439

	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
440 441 442
	mesg = (struct atmlec_msg *)skb->data;
	tmp = skb->data;
	tmp += sizeof(struct atmlec_msg);
443
	pr_debug("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
	switch (mesg->type) {
	case l_set_mac_addr:
		for (i = 0; i < 6; i++) {
			dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
		}
		break;
	case l_del_mac_addr:
		for (i = 0; i < 6; i++) {
			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 已提交
466
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
467 468
		entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
		lec_arp_remove(priv, entry);
L
Linus Torvalds 已提交
469 470
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

471 472 473 474 475 476 477 478
		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);
479
		pr_debug("lec: in l_arp_update\n");
480
		if (mesg->sizeoftlvs != 0) {	/* LANE2 3.1.5 */
481
			pr_debug("lec: LANE2 3.1.5, got tlvs, size %d\n",
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
				mesg->sizeoftlvs);
			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);
		priv->lane_version = mesg->content.config.lane_version;	/* LANE2 */
L
Linus Torvalds 已提交
502 503 504
		priv->lane2_ops = NULL;
		if (priv->lane_version > 1)
			priv->lane2_ops = &lane2_ops;
S
Stephen Hemminger 已提交
505
		if (dev_set_mtu(dev, mesg->content.config.mtu))
L
Linus Torvalds 已提交
506
			printk("%s: change_mtu to %d failed\n", dev->name,
507
			       mesg->content.config.mtu);
L
Linus Torvalds 已提交
508
		priv->is_proxy = mesg->content.config.is_proxy;
509 510 511 512 513 514 515 516 517 518
		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 已提交
519
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
520
		{
J
Johannes Berg 已提交
521 522
			pr_debug("%s: bridge zeppelin asks about %pM\n",
				 dev->name, mesg->content.proxy.mac_addr);
523

524
			if (br_fdb_test_addr_hook == NULL)
525 526
				break;

527 528
			if (br_fdb_test_addr_hook(dev,
					mesg->content.proxy.mac_addr)) {
529 530 531 532
				/* hit from bridge table, send LE_ARP_RESPONSE */
				struct sk_buff *skb2;
				struct sock *sk;

533
				pr_debug
534 535 536 537 538
				    ("%s: entry found, responding to zeppelin\n",
				     dev->name);
				skb2 =
				    alloc_skb(sizeof(struct atmlec_msg),
					      GFP_ATOMIC);
539
				if (skb2 == NULL)
540 541
					break;
				skb2->len = sizeof(struct atmlec_msg);
542 543
				skb_copy_to_linear_data(skb2, mesg,
							sizeof(*mesg));
544 545 546 547 548 549
				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);
			}
		}
L
Linus Torvalds 已提交
550
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
551 552 553 554 555 556 557 558
		break;
	default:
		printk("%s: Unknown message type %d\n", dev->name, mesg->type);
		dev_kfree_skb(skb);
		return -EINVAL;
	}
	dev_kfree_skb(skb);
	return 0;
L
Linus Torvalds 已提交
559 560
}

561
static void lec_atm_close(struct atm_vcc *vcc)
L
Linus Torvalds 已提交
562
{
563 564
	struct sk_buff *skb;
	struct net_device *dev = (struct net_device *)vcc->proto_data;
565
	struct lec_priv *priv = netdev_priv(dev);
L
Linus Torvalds 已提交
566

567 568
	priv->lecd = NULL;
	/* Do something needful? */
L
Linus Torvalds 已提交
569

570 571
	netif_stop_queue(dev);
	lec_arp_destroy(priv);
L
Linus Torvalds 已提交
572

573
	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
L
Linus Torvalds 已提交
574
		printk("%s lec_atm_close: closing with messages pending\n",
575 576 577
		       dev->name);
	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
		atm_return(vcc, skb->truesize);
L
Linus Torvalds 已提交
578
		dev_kfree_skb(skb);
579 580
	}

L
Linus Torvalds 已提交
581
	printk("%s: Shut down!\n", dev->name);
582
	module_put(THIS_MODULE);
L
Linus Torvalds 已提交
583 584 585
}

static struct atmdev_ops lecdev_ops = {
586 587
	.close = lec_atm_close,
	.send = lec_atm_send
L
Linus Torvalds 已提交
588 589 590
};

static struct atm_dev lecatm_dev = {
591 592 593
	.ops = &lecdev_ops,
	.type = "lec",
	.number = 999,		/* dummy device number */
594
	.lock = __SPIN_LOCK_UNLOCKED(lecatm_dev.lock)
L
Linus Torvalds 已提交
595 596 597 598 599 600
};

/*
 * LANE2: new argument struct sk_buff *data contains
 * the LE_ARP based TLVs introduced in the LANE2 spec
 */
601 602
static int
send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
603
	     const unsigned char *mac_addr, const unsigned char *atm_addr,
604
	     struct sk_buff *data)
L
Linus Torvalds 已提交
605 606 607 608 609 610 611 612 613 614 615 616 617
{
	struct sock *sk;
	struct sk_buff *skb;
	struct atmlec_msg *mesg;

	if (!priv || !priv->lecd) {
		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;
618
	memset(mesg, 0, sizeof(struct atmlec_msg));
L
Linus Torvalds 已提交
619
	mesg->type = type;
620 621
	if (data != NULL)
		mesg->sizeoftlvs = data->len;
L
Linus Torvalds 已提交
622 623
	if (mac_addr)
		memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
624 625
	else
		mesg->content.normal.targetless_le_arp = 1;
L
Linus Torvalds 已提交
626 627 628
	if (atm_addr)
		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);

629
	atm_force_charge(priv->lecd, skb->truesize);
L
Linus Torvalds 已提交
630 631
	sk = sk_atm(priv->lecd);
	skb_queue_tail(&sk->sk_receive_queue, skb);
632
	sk->sk_data_ready(sk, skb->len);
L
Linus Torvalds 已提交
633

634
	if (data != NULL) {
635
		pr_debug("lec: about to send %d bytes of data\n", data->len);
636 637 638 639
		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 已提交
640

641
	return 0;
L
Linus Torvalds 已提交
642 643 644 645 646
}

/* shamelessly stolen from drivers/net/net_init.c */
static int lec_change_mtu(struct net_device *dev, int new_mtu)
{
647 648 649 650
	if ((new_mtu < 68) || (new_mtu > 18190))
		return -EINVAL;
	dev->mtu = new_mtu;
	return 0;
L
Linus Torvalds 已提交
651 652 653 654
}

static void lec_set_multicast_list(struct net_device *dev)
{
655 656 657 658 659
	/*
	 * by default, all multicast frames arrive over the bus.
	 * eventually support selective multicast service
	 */
	return;
L
Linus Torvalds 已提交
660 661
}

662 663 664 665 666 667 668 669 670 671
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,
};


672
static void lec_init(struct net_device *dev)
L
Linus Torvalds 已提交
673
{
674
	dev->netdev_ops = &lec_netdev_ops;
675
	printk("%s: Initialized!\n", dev->name);
L
Linus Torvalds 已提交
676 677
}

678
static const unsigned char lec_ctrl_magic[] = {
679 680 681 682 683
	0xff,
	0x00,
	0x01,
	0x01
};
L
Linus Torvalds 已提交
684

685 686 687 688
#define LEC_DATA_DIRECT_8023  2
#define LEC_DATA_DIRECT_8025  3

static int lec_is_data_direct(struct atm_vcc *vcc)
689
{
690 691
	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));
692
}
693

694
static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
695
{
696
	unsigned long flags;
697
	struct net_device *dev = (struct net_device *)vcc->proto_data;
698
	struct lec_priv *priv = netdev_priv(dev);
L
Linus Torvalds 已提交
699 700

#if DUMP_PACKETS >0
701 702
	int i = 0;
	char buf[300];
L
Linus Torvalds 已提交
703

704 705
	printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
	       vcc->vpi, vcc->vci);
L
Linus Torvalds 已提交
706
#endif
707
	if (!skb) {
708
		pr_debug("%s: null skb\n", dev->name);
709 710 711
		lec_vcc_close(priv, vcc);
		return;
	}
L
Linus Torvalds 已提交
712
#if DUMP_PACKETS > 0
713 714
	printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
	       skb->len, priv->lecid);
L
Linus Torvalds 已提交
715
#if DUMP_PACKETS >= 2
716 717 718
	for (i = 0; i < skb->len && i < 99; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
719
#elif DUMP_PACKETS >= 1
720 721 722
	for (i = 0; i < skb->len && i < 30; i++) {
		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
	}
L
Linus Torvalds 已提交
723
#endif /* DUMP_PACKETS >= 1 */
724 725 726 727
	if (i == skb->len)
		printk("%s\n", buf);
	else
		printk("%s...\n", buf);
L
Linus Torvalds 已提交
728
#endif /* DUMP_PACKETS > 0 */
729
	if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {	/* Control frame, to daemon */
L
Linus Torvalds 已提交
730 731
		struct sock *sk = sk_atm(vcc);

732
		pr_debug("%s: To daemon\n", dev->name);
733 734 735
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
	} else {		/* Data frame, queue to protocol handlers */
736
		struct lec_arp_table *entry;
737 738 739
		unsigned char *src, *dst;

		atm_return(vcc, skb->truesize);
A
Al Viro 已提交
740
		if (*(__be16 *) skb->data == htons(priv->lecid) ||
741 742 743 744 745
		    !priv->lecd || !(dev->flags & IFF_UP)) {
			/*
			 * Probably looping back, or if lecd is missing,
			 * lecd has gone down
			 */
746
			pr_debug("Ignoring frame...\n");
747 748 749
			dev_kfree_skb(skb);
			return;
		}
L
Linus Torvalds 已提交
750
#ifdef CONFIG_TR
751 752 753
		if (priv->is_trdev)
			dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
		else
L
Linus Torvalds 已提交
754
#endif
755
			dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
756

757 758
		/*
		 * If this is a Data Direct VCC, and the VCC does not match
759 760 761 762 763 764
		 * 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)
765 766 767
				src =
				    ((struct lecdatahdr_8025 *)skb->data)->
				    h_source;
768 769
			else
#endif
770 771 772
				src =
				    ((struct lecdatahdr_8023 *)skb->data)->
				    h_source;
773 774 775
			entry = lec_arp_find(priv, src);
			if (entry && entry->vcc != vcc) {
				lec_arp_remove(priv, entry);
776
				lec_arp_put(entry);
777 778 779
			}
		}
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
L
Linus Torvalds 已提交
780

781 782
		if (!(dst[0] & 0x01) &&	/* Never filter Multi/Broadcast */
		    !priv->is_proxy &&	/* Proxy wants all the packets */
L
Linus Torvalds 已提交
783
		    memcmp(dst, dev->dev_addr, dev->addr_len)) {
784 785 786
			dev_kfree_skb(skb);
			return;
		}
787
		if (!hlist_empty(&priv->lec_arp_empty_ones)) {
788 789 790
			lec_arp_check_empties(priv, vcc, skb);
		}
		skb_pull(skb, 2);	/* skip lec_id */
L
Linus Torvalds 已提交
791
#ifdef CONFIG_TR
792 793 794
		if (priv->is_trdev)
			skb->protocol = tr_type_trans(skb, dev);
		else
L
Linus Torvalds 已提交
795
#endif
796
			skb->protocol = eth_type_trans(skb, dev);
797 798
		dev->stats.rx_packets++;
		dev->stats.rx_bytes += skb->len;
799 800 801
		memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
		netif_rx(skb);
	}
L
Linus Torvalds 已提交
802 803
}

804
static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
{
	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
	struct net_device *dev = skb->dev;

	if (vpriv == NULL) {
		printk("lec_pop(): vpriv = NULL!?!?!?\n");
		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);
	}
}

823
static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
L
Linus Torvalds 已提交
824 825
{
	struct lec_vcc_priv *vpriv;
826 827 828 829 830 831 832 833 834 835 836 837 838
	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));
	if (bytes_left != 0) {
		printk
		    ("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
		     bytes_left);
	}
	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
	    !dev_lec[ioc_data.dev_num])
		return -EINVAL;
L
Linus Torvalds 已提交
839 840 841 842 843 844
	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
	vcc->pop = lec_pop;
845
	lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]),
846 847 848 849
		      &ioc_data, vcc, vcc->push);
	vcc->proto_data = dev_lec[ioc_data.dev_num];
	vcc->push = lec_push;
	return 0;
L
Linus Torvalds 已提交
850 851
}

852
static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
L
Linus Torvalds 已提交
853
{
854 855 856
	if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
		return -EINVAL;
	vcc->proto_data = dev_lec[arg];
857 858
	return lec_mcast_make((struct lec_priv *)netdev_priv(dev_lec[arg]),
				vcc);
L
Linus Torvalds 已提交
859 860 861
}

/* Initialize device. */
862 863 864 865 866 867 868 869 870
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 已提交
871
#ifdef CONFIG_TR
872 873 874 875 876
	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 已提交
877
#endif
878 879
	if (!dev_lec[i]) {
		int is_trdev, size;
L
Linus Torvalds 已提交
880

881 882 883
		is_trdev = 0;
		if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
			is_trdev = 1;
L
Linus Torvalds 已提交
884

885
		size = sizeof(struct lec_priv);
L
Linus Torvalds 已提交
886
#ifdef CONFIG_TR
887 888 889
		if (is_trdev)
			dev_lec[i] = alloc_trdev(size);
		else
L
Linus Torvalds 已提交
890
#endif
891 892 893 894 895 896 897 898 899
			dev_lec[i] = alloc_etherdev(size);
		if (!dev_lec[i])
			return -ENOMEM;
		snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
		if (register_netdev(dev_lec[i])) {
			free_netdev(dev_lec[i]);
			return -EINVAL;
		}

900
		priv = netdev_priv(dev_lec[i]);
901 902 903
		priv->is_trdev = is_trdev;
		lec_init(dev_lec[i]);
	} else {
904
		priv = netdev_priv(dev_lec[i]);
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
		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);

	if (dev_lec[i]->flags & IFF_UP) {
		netif_start_queue(dev_lec[i]);
	}
	__module_get(THIS_MODULE);
	return i;
L
Linus Torvalds 已提交
935 936 937
}

#ifdef CONFIG_PROC_FS
938
static char *lec_arp_get_status_string(unsigned char status)
L
Linus Torvalds 已提交
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
{
	static char *lec_arp_status_string[] = {
		"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
968
		seq_printf(seq, "        ");
L
Linus Torvalds 已提交
969 970 971
	if (entry->recv_vcc) {
		seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,
			   entry->recv_vcc->vci);
972 973
	}
	seq_putc(seq, '\n');
L
Linus Torvalds 已提交
974 975 976 977 978
}

struct lec_state {
	unsigned long flags;
	struct lec_priv *locked;
979
	struct hlist_node *node;
L
Linus Torvalds 已提交
980 981 982 983 984 985
	struct net_device *dev;
	int itf;
	int arp_table;
	int misc_table;
};

986
static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
L
Linus Torvalds 已提交
987 988
			  loff_t *l)
{
989 990
	struct hlist_node *e = state->node;
	struct lec_arp_table *tmp;
L
Linus Torvalds 已提交
991 992

	if (!e)
993
		e = tbl->first;
J
Joe Perches 已提交
994
	if (e == SEQ_START_TOKEN) {
995
		e = tbl->first;
L
Linus Torvalds 已提交
996 997
		--*l;
	}
998 999

	hlist_for_each_entry_from(tmp, e, next) {
L
Linus Torvalds 已提交
1000 1001 1002
		if (--*l < 0)
			break;
	}
1003 1004
	state->node = e;

L
Linus Torvalds 已提交
1005 1006 1007 1008
	return (*l < 0) ? state : NULL;
}

static void *lec_arp_walk(struct lec_state *state, loff_t *l,
1009
			  struct lec_priv *priv)
L
Linus Torvalds 已提交
1010 1011 1012 1013 1014
{
	void *v = NULL;
	int p;

	for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
1015
		v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
L
Linus Torvalds 已提交
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
		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)
{
1026 1027 1028 1029
	struct hlist_head *lec_misc_tables[] = {
		&priv->lec_arp_empty_ones,
		&priv->lec_no_forward,
		&priv->mcast_fwds
L
Linus Torvalds 已提交
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
	};
	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);
	}
1050
	if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
L
Linus Torvalds 已提交
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
		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];
1065 1066
	v = (dev && netdev_priv(dev)) ?
		lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
L
Linus Torvalds 已提交
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
	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;
	}
1085
	return v;
L
Linus Torvalds 已提交
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
}

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

J
Joe Perches 已提交
1099
	return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
L
Linus Torvalds 已提交
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
}

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)
{
1124 1125 1126
	static char lec_banner[] = "Itf  MAC          ATM destination"
	    "                          Status            Flags "
	    "VPI/VCI Recv VPI/VCI\n";
L
Linus Torvalds 已提交
1127

J
Joe Perches 已提交
1128
	if (v == SEQ_START_TOKEN)
L
Linus Torvalds 已提交
1129 1130 1131
		seq_puts(seq, lec_banner);
	else {
		struct lec_state *state = seq->private;
1132
		struct net_device *dev = state->dev;
1133
		struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next);
L
Linus Torvalds 已提交
1134 1135

		seq_printf(seq, "%s ", dev->name);
1136
		lec_info(seq, entry);
L
Linus Torvalds 已提交
1137 1138 1139 1140
	}
	return 0;
}

1141
static const struct seq_operations lec_seq_ops = {
1142 1143 1144 1145
	.start = lec_seq_start,
	.next = lec_seq_next,
	.stop = lec_seq_stop,
	.show = lec_seq_show,
L
Linus Torvalds 已提交
1146 1147 1148 1149
};

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

1153
static const struct file_operations lec_seq_fops = {
1154 1155 1156 1157
	.owner = THIS_MODULE,
	.open = lec_seq_open,
	.read = seq_read,
	.llseek = seq_lseek,
1158
	.release = seq_release_private,
L
Linus Torvalds 已提交
1159 1160 1161 1162 1163 1164 1165
};
#endif

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

L
Linus Torvalds 已提交
1167
	switch (cmd) {
1168 1169 1170 1171 1172 1173 1174 1175
	case ATMLEC_CTRL:
	case ATMLEC_MCAST:
	case ATMLEC_DATA:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		break;
	default:
		return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
1176 1177 1178
	}

	switch (cmd) {
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
	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 已提交
1190 1191 1192 1193 1194 1195
	}

	return err;
}

static struct atm_ioctl lane_ioctl_ops = {
1196 1197
	.owner = THIS_MODULE,
	.ioctl = lane_ioctl,
L
Linus Torvalds 已提交
1198 1199 1200 1201 1202 1203 1204
};

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

1205
	p = proc_create("lec", S_IRUGO, atm_proc_root, &lec_seq_fops);
1206 1207 1208 1209
	if (!p) {
		printk(KERN_ERR "Unable to initialize /proc/net/atm/lec\n");
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
1210 1211 1212
#endif

	register_atm_ioctl(&lane_ioctl_ops);
1213 1214
	printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
	return 0;
L
Linus Torvalds 已提交
1215 1216 1217 1218
}

static void __exit lane_module_cleanup(void)
{
1219 1220
	int i;
	struct lec_priv *priv;
L
Linus Torvalds 已提交
1221 1222 1223 1224 1225

	remove_proc_entry("lec", atm_proc_root);

	deregister_atm_ioctl(&lane_ioctl_ops);

1226 1227
	for (i = 0; i < MAX_LEC_ITF; i++) {
		if (dev_lec[i] != NULL) {
1228
			priv = netdev_priv(dev_lec[i]);
L
Linus Torvalds 已提交
1229
			unregister_netdev(dev_lec[i]);
1230 1231 1232 1233
			free_netdev(dev_lec[i]);
			dev_lec[i] = NULL;
		}
	}
L
Linus Torvalds 已提交
1234

1235
	return;
L
Linus Torvalds 已提交
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
}

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
 */
1248
static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
1249
			 u8 **tlvs, u32 *sizeoftlvs)
L
Linus Torvalds 已提交
1250 1251
{
	unsigned long flags;
1252
	struct lec_priv *priv = netdev_priv(dev);
1253 1254 1255
	struct lec_arp_table *table;
	struct sk_buff *skb;
	int retval;
L
Linus Torvalds 已提交
1256

1257
	if (force == 0) {
L
Linus Torvalds 已提交
1258
		spin_lock_irqsave(&priv->lec_arp_lock, flags);
1259
		table = lec_arp_find(priv, dst_mac);
L
Linus Torvalds 已提交
1260
		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1261 1262 1263
		if (table == NULL)
			return -1;

1264
		*tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
1265 1266 1267 1268 1269 1270 1271
		if (*tlvs == NULL)
			return -1;

		*sizeoftlvs = table->sizeoftlvs;

		return 0;
	}
L
Linus Torvalds 已提交
1272 1273 1274

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

L
Linus Torvalds 已提交
1276 1277 1278 1279 1280
	else {
		skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
		if (skb == NULL)
			return -1;
		skb->len = *sizeoftlvs;
1281
		skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);
L
Linus Torvalds 已提交
1282 1283
		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
	}
1284 1285
	return retval;
}
L
Linus Torvalds 已提交
1286 1287 1288 1289 1290 1291 1292 1293

/*
 * 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)
 *
 */
1294 1295
static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
			       const u8 *tlvs, u32 sizeoftlvs)
L
Linus Torvalds 已提交
1296
{
1297 1298
	int retval;
	struct sk_buff *skb;
1299
	struct lec_priv *priv = netdev_priv(dev);
1300 1301 1302 1303 1304 1305

	if (compare_ether_addr(lan_dst, dev->dev_addr))
		return (0);	/* not our mac address */

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

1306
	priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1307 1308 1309 1310 1311 1312 1313 1314
	if (priv->tlvs == NULL)
		return (0);
	priv->sizeoftlvs = sizeoftlvs;

	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
	if (skb == NULL)
		return 0;
	skb->len = sizeoftlvs;
1315
	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
1316 1317 1318 1319 1320 1321 1322 1323
	retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
	if (retval != 0)
		printk("lec.c: lane2_associate_req() failed\n");
	/*
	 * If the previous association has changed we must
	 * somehow notify other LANE entities about the change
	 */
	return (1);
L
Linus Torvalds 已提交
1324 1325 1326 1327 1328 1329
}

/*
 * LANE2: 3.1.5, LE_ASSOCIATE.indication
 *
 */
1330 1331
static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
				const u8 *tlvs, u32 sizeoftlvs)
L
Linus Torvalds 已提交
1332 1333
{
#if 0
1334
	int i = 0;
L
Linus Torvalds 已提交
1335
#endif
1336
	struct lec_priv *priv = netdev_priv(dev);
1337 1338 1339 1340 1341 1342 1343
#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 已提交
1344

1345 1346
	if (entry == NULL)
		return;		/* should not happen */
L
Linus Torvalds 已提交
1347

1348
	kfree(entry->tlvs);
L
Linus Torvalds 已提交
1349

1350
	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1351 1352 1353
	if (entry->tlvs == NULL)
		return;
	entry->sizeoftlvs = sizeoftlvs;
L
Linus Torvalds 已提交
1354 1355
#endif
#if 0
1356 1357 1358 1359 1360 1361
	printk("lec.c: lane2_associate_ind()\n");
	printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
	while (i < sizeoftlvs)
		printk("%02x ", tlvs[i++]);

	printk("\n");
L
Linus Torvalds 已提交
1362 1363
#endif

1364 1365 1366 1367 1368 1369
	/* 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);
	}
	return;
L
Linus Torvalds 已提交
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
}

/*
 * 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>
#include <asm/param.h>
#include <asm/atomic.h>
#include <linux/inetdevice.h>
#include <net/route.h>

#if 0
1387
#define pr_debug(format,args...)
L
Linus Torvalds 已提交
1388
/*
1389
#define pr_debug printk
L
Linus Torvalds 已提交
1390 1391 1392 1393 1394 1395
*/
#endif
#define DEBUG_ARP_TABLE 0

#define LEC_ARP_REFRESH_INTERVAL (3*HZ)

D
David Howells 已提交
1396
static void lec_arp_check_expire(struct work_struct *work);
L
Linus Torvalds 已提交
1397 1398
static void lec_arp_expire_arp(unsigned long data);

1399
/*
L
Linus Torvalds 已提交
1400 1401 1402 1403 1404 1405 1406 1407
 * Arp table funcs
 */

#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))

/*
 * Initialization of arp-cache
 */
1408
static void lec_arp_init(struct lec_priv *priv)
L
Linus Torvalds 已提交
1409
{
1410
	unsigned short i;
L
Linus Torvalds 已提交
1411

1412
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1413
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1414
	}
1415 1416 1417
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
	INIT_HLIST_HEAD(&priv->lec_no_forward);
	INIT_HLIST_HEAD(&priv->mcast_fwds);
L
Linus Torvalds 已提交
1418
	spin_lock_init(&priv->lec_arp_lock);
D
David Howells 已提交
1419
	INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
1420
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
L
Linus Torvalds 已提交
1421 1422
}

1423
static void lec_arp_clear_vccs(struct lec_arp_table *entry)
L
Linus Torvalds 已提交
1424
{
1425
	if (entry->vcc) {
L
Linus Torvalds 已提交
1426 1427
		struct atm_vcc *vcc = entry->vcc;
		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
1428
		struct net_device *dev = (struct net_device *)vcc->proto_data;
L
Linus Torvalds 已提交
1429

1430
		vcc->pop = vpriv->old_pop;
L
Linus Torvalds 已提交
1431 1432 1433 1434
		if (vpriv->xoff)
			netif_wake_queue(dev);
		kfree(vpriv);
		vcc->user_back = NULL;
1435
		vcc->push = entry->old_push;
L
Linus Torvalds 已提交
1436
		vcc_release_async(vcc, -EPIPE);
1437
		entry->vcc = NULL;
1438 1439 1440
	}
	if (entry->recv_vcc) {
		entry->recv_vcc->push = entry->old_recv_push;
L
Linus Torvalds 已提交
1441
		vcc_release_async(entry->recv_vcc, -EPIPE);
1442 1443
		entry->recv_vcc = NULL;
	}
L
Linus Torvalds 已提交
1444 1445 1446 1447 1448 1449
}

/*
 * Insert entry to lec_arp_table
 * LANE2: Add to the end of the list to satisfy 8.1.13
 */
1450
static inline void
1451
lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
L
Linus Torvalds 已提交
1452
{
1453
	struct hlist_head *tmp;
1454

1455 1456
	tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
	hlist_add_head(&entry->next, tmp);
1457

1458
	pr_debug("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1459 1460 1461
		0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1],
		0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3],
		0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]);
L
Linus Torvalds 已提交
1462 1463 1464 1465 1466
}

/*
 * Remove entry from lec_arp_table
 */
1467 1468
static int
lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
L
Linus Torvalds 已提交
1469
{
1470 1471 1472
	struct hlist_node *node;
	struct lec_arp_table *entry;
	int i, remove_vcc = 1;
1473 1474 1475 1476

	if (!to_remove) {
		return -1;
	}
1477 1478

	hlist_del(&to_remove->next);
1479 1480
	del_timer(&to_remove->timer);

1481
	/* If this is the only MAC connected to this VCC, also tear down the VCC */
1482 1483 1484 1485
	if (to_remove->status >= ESI_FLUSH_PENDING) {
		/*
		 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
		 */
1486 1487 1488 1489
		for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
			hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
				if (memcmp(to_remove->atm_addr,
					   entry->atm_addr, ATM_ESA_LEN) == 0) {
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
					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? */

1500
	pr_debug("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1501 1502 1503 1504
		0xff & to_remove->mac_addr[0], 0xff & to_remove->mac_addr[1],
		0xff & to_remove->mac_addr[2], 0xff & to_remove->mac_addr[3],
		0xff & to_remove->mac_addr[4], 0xff & to_remove->mac_addr[5]);
	return 0;
L
Linus Torvalds 已提交
1505 1506 1507
}

#if DEBUG_ARP_TABLE
1508
static char *get_status_string(unsigned char st)
L
Linus Torvalds 已提交
1509
{
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
	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";
	default:
		return "<UNKNOWN>";
	}
L
Linus Torvalds 已提交
1524 1525
}

1526
static void dump_arp_table(struct lec_priv *priv)
L
Linus Torvalds 已提交
1527
{
1528
	struct hlist_node *node;
1529
	struct lec_arp_table *rulla;
1530 1531
	char buf[256];
	int i, j, offset;
1532 1533 1534

	printk("Dump %p:\n", priv);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1535 1536 1537
		hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) {
			offset = 0;
			offset += sprintf(buf, "%d: %p\n", i, rulla);
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563
			offset += sprintf(buf + offset, "Mac:");
			for (j = 0; j < ETH_ALEN; j++) {
				offset += sprintf(buf + offset,
						  "%2.2x ",
						  rulla->mac_addr[j] & 0xff);
			}
			offset += sprintf(buf + offset, "Atm:");
			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));
1564
			printk("%s\n", buf);
1565 1566
		}
	}
1567 1568

	if (!hlist_empty(&priv->lec_no_forward))
1569
		printk("No forward\n");
1570
	hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
		offset = 0;
		offset += sprintf(buf + offset, "Mac:");
		for (j = 0; j < ETH_ALEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->mac_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset, "Atm:");
		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));
1594
		printk("%s\n", buf);
1595
	}
1596 1597

	if (!hlist_empty(&priv->lec_arp_empty_ones))
1598
		printk("Empty ones\n");
1599
	hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
		offset = 0;
		offset += sprintf(buf + offset, "Mac:");
		for (j = 0; j < ETH_ALEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->mac_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset, "Atm:");
		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));
		printk("%s", buf);
	}

1626
	if (!hlist_empty(&priv->mcast_fwds))
1627
		printk("Multicast Forward VCCs\n");
1628
	hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651
		offset = 0;
		offset += sprintf(buf + offset, "Mac:");
		for (j = 0; j < ETH_ALEN; j++) {
			offset += sprintf(buf + offset, "%2.2x ",
					  rulla->mac_addr[j] & 0xff);
		}
		offset += sprintf(buf + offset, "Atm:");
		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));
1652
		printk("%s\n", buf);
1653
	}
L
Linus Torvalds 已提交
1654 1655

}
1656 1657 1658
#else
#define dump_arp_table(priv) do { } while (0)
#endif
L
Linus Torvalds 已提交
1659 1660 1661 1662

/*
 * Destruction of arp-cache
 */
1663
static void lec_arp_destroy(struct lec_priv *priv)
L
Linus Torvalds 已提交
1664 1665
{
	unsigned long flags;
1666 1667
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1668 1669
	int i;

1670
	cancel_rearming_delayed_work(&priv->lec_arp_work);
L
Linus Torvalds 已提交
1671

1672 1673 1674
	/*
	 * Remove all entries
	 */
L
Linus Torvalds 已提交
1675 1676

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1677
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1678
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
1679
			lec_arp_remove(priv, entry);
1680
			lec_arp_put(entry);
1681
		}
1682
		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
1683
	}
1684 1685

	hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
1686 1687
		del_timer_sync(&entry->timer);
		lec_arp_clear_vccs(entry);
1688
		hlist_del(&entry->next);
1689
		lec_arp_put(entry);
1690
	}
1691 1692 1693
	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);

	hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
1694 1695
		del_timer_sync(&entry->timer);
		lec_arp_clear_vccs(entry);
1696
		hlist_del(&entry->next);
1697
		lec_arp_put(entry);
1698
	}
1699 1700 1701
	INIT_HLIST_HEAD(&priv->lec_no_forward);

	hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
1702 1703
		/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
		lec_arp_clear_vccs(entry);
1704
		hlist_del(&entry->next);
1705
		lec_arp_put(entry);
1706
	}
1707
	INIT_HLIST_HEAD(&priv->mcast_fwds);
1708
	priv->mcast_vcc = NULL;
L
Linus Torvalds 已提交
1709 1710 1711
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

1712
/*
L
Linus Torvalds 已提交
1713 1714
 * Find entry by mac_address
 */
1715
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
1716
					  const unsigned char *mac_addr)
L
Linus Torvalds 已提交
1717
{
1718 1719 1720
	struct hlist_node *node;
	struct hlist_head *head;
	struct lec_arp_table *entry;
1721

1722
	pr_debug("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1723 1724 1725
		mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff,
		mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff);

1726 1727 1728 1729
	head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
	hlist_for_each_entry(entry, node, head, next) {
		if (!compare_ether_addr(mac_addr, entry->mac_addr)) {
			return entry;
1730 1731 1732
		}
	}
	return NULL;
L
Linus Torvalds 已提交
1733 1734
}

1735
static struct lec_arp_table *make_entry(struct lec_priv *priv,
1736
					const unsigned char *mac_addr)
L
Linus Torvalds 已提交
1737
{
1738 1739 1740 1741 1742 1743 1744 1745
	struct lec_arp_table *to_return;

	to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
	if (!to_return) {
		printk("LEC: Arp entry kmalloc failed\n");
		return NULL;
	}
	memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
1746
	INIT_HLIST_NODE(&to_return->next);
1747 1748
	setup_timer(&to_return->timer, lec_arp_expire_arp,
			(unsigned long)to_return);
1749 1750 1751
	to_return->last_used = jiffies;
	to_return->priv = priv;
	skb_queue_head_init(&to_return->tx_wait);
1752
	atomic_set(&to_return->usage, 1);
1753
	return to_return;
L
Linus Torvalds 已提交
1754 1755
}

1756 1757
/* Arp sent timer expired */
static void lec_arp_expire_arp(unsigned long data)
L
Linus Torvalds 已提交
1758
{
1759 1760 1761 1762
	struct lec_arp_table *entry;

	entry = (struct lec_arp_table *)data;

1763
	pr_debug("lec_arp_expire_arp\n");
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775
	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 已提交
1776 1777
}

1778 1779
/* Unknown/unused vcc expire, remove associated entry */
static void lec_arp_expire_vcc(unsigned long data)
L
Linus Torvalds 已提交
1780 1781
{
	unsigned long flags;
1782 1783
	struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
	struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
L
Linus Torvalds 已提交
1784

1785
	del_timer(&to_remove->timer);
L
Linus Torvalds 已提交
1786

1787
	pr_debug("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
1788 1789 1790
		to_remove, priv,
		to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
		to_remove->vcc ? to_remove->recv_vcc->vci : 0);
L
Linus Torvalds 已提交
1791 1792

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1793
	hlist_del(&to_remove->next);
L
Linus Torvalds 已提交
1794 1795
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

1796
	lec_arp_clear_vccs(to_remove);
1797
	lec_arp_put(to_remove);
L
Linus Torvalds 已提交
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
}

/*
 * 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 已提交
1816
static void lec_arp_check_expire(struct work_struct *work)
L
Linus Torvalds 已提交
1817 1818
{
	unsigned long flags;
D
David Howells 已提交
1819 1820
	struct lec_priv *priv =
		container_of(work, struct lec_priv, lec_arp_work.work);
1821 1822
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1823 1824 1825 1826
	unsigned long now;
	unsigned long time_to_check;
	int i;

1827
	pr_debug("lec_arp_check_expire %p\n", priv);
L
Linus Torvalds 已提交
1828
	now = jiffies;
1829
restart:
L
Linus Torvalds 已提交
1830
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1831
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1832
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
1833
			if ((entry->flags) & LEC_REMOTE_FLAG &&
L
Linus Torvalds 已提交
1834 1835 1836 1837 1838
			    priv->topology_change)
				time_to_check = priv->forward_delay_time;
			else
				time_to_check = priv->aging_time;

1839
			pr_debug("About to expire: %lx - %lx > %lx\n",
1840 1841 1842 1843
				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 */
L
Linus Torvalds 已提交
1844
				/* Remove entry */
1845
				pr_debug("LEC:Entry timed out\n");
L
Linus Torvalds 已提交
1846
				lec_arp_remove(priv, entry);
1847
				lec_arp_put(entry);
L
Linus Torvalds 已提交
1848 1849 1850
			} else {
				/* Something else */
				if ((entry->status == ESI_VC_PENDING ||
1851
				     entry->status == ESI_ARP_PENDING)
L
Linus Torvalds 已提交
1852
				    && time_after_eq(now,
1853 1854 1855
						     entry->timestamp +
						     priv->
						     max_unknown_frame_time)) {
L
Linus Torvalds 已提交
1856 1857 1858
					entry->timestamp = jiffies;
					entry->packets_flooded = 0;
					if (entry->status == ESI_VC_PENDING)
1859 1860 1861 1862
						send_to_lecd(priv, l_svc_setup,
							     entry->mac_addr,
							     entry->atm_addr,
							     NULL);
L
Linus Torvalds 已提交
1863
				}
1864 1865 1866 1867
				if (entry->status == ESI_FLUSH_PENDING
				    &&
				    time_after_eq(now, entry->timestamp +
						  priv->path_switching_delay)) {
L
Linus Torvalds 已提交
1868
					struct sk_buff *skb;
1869
					struct atm_vcc *vcc = entry->vcc;
L
Linus Torvalds 已提交
1870

1871 1872 1873
					lec_arp_hold(entry);
					spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
					while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
1874
						lec_send(vcc, skb);
L
Linus Torvalds 已提交
1875
					entry->last_used = jiffies;
1876
					entry->status = ESI_FORWARD_DIRECT;
1877 1878
					lec_arp_put(entry);
					goto restart;
L
Linus Torvalds 已提交
1879 1880 1881 1882 1883 1884
				}
			}
		}
	}
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);

1885
	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
L
Linus Torvalds 已提交
1886
}
1887

L
Linus Torvalds 已提交
1888 1889
/*
 * Try to find vcc where mac_address is attached.
1890
 *
L
Linus Torvalds 已提交
1891
 */
1892
static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
1893
				       const unsigned char *mac_to_find, int is_rdesc,
1894
				       struct lec_arp_table **ret_entry)
L
Linus Torvalds 已提交
1895 1896
{
	unsigned long flags;
1897
	struct lec_arp_table *entry;
L
Linus Torvalds 已提交
1898 1899
	struct atm_vcc *found;

1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911
	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 已提交
1912 1913

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1914 1915 1916 1917 1918 1919
	entry = lec_arp_find(priv, mac_to_find);

	if (entry) {
		if (entry->status == ESI_FORWARD_DIRECT) {
			/* Connection Ok */
			entry->last_used = jiffies;
1920
			lec_arp_hold(entry);
1921 1922
			*ret_entry = entry;
			found = entry->vcc;
L
Linus Torvalds 已提交
1923
			goto out;
1924 1925 1926
		}
		/*
		 * If the LE_ARP cache entry is still pending, reset count to 0
1927 1928 1929 1930 1931
		 * so another LE_ARP request can be made for this frame.
		 */
		if (entry->status == ESI_ARP_PENDING) {
			entry->no_tries = 0;
		}
1932 1933 1934 1935 1936 1937 1938 1939 1940 1941
		/*
		 * 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++;
1942
			pr_debug("LEC_ARP: Flooding..\n");
1943
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1944
			goto out;
1945 1946 1947
		}
		/*
		 * We got here because entry->status == ESI_FLUSH_PENDING
L
Linus Torvalds 已提交
1948 1949 1950
		 * or BUS flood limit was reached for an entry which is
		 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
		 */
1951
		lec_arp_hold(entry);
1952
		*ret_entry = entry;
1953
		pr_debug("lec: entry->status %d entry->vcc %p\n", entry->status,
1954 1955 1956 1957 1958
			entry->vcc);
		found = NULL;
	} else {
		/* No matching entry was found */
		entry = make_entry(priv, mac_to_find);
1959
		pr_debug("LEC_ARP: Making entry\n");
1960 1961
		if (!entry) {
			found = priv->mcast_vcc;
L
Linus Torvalds 已提交
1962
			goto out;
1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980
		}
		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 已提交
1981 1982 1983 1984 1985 1986 1987

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

static int
1988
lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr,
1989
		unsigned long permanent)
L
Linus Torvalds 已提交
1990 1991
{
	unsigned long flags;
1992 1993
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
1994
	int i;
L
Linus Torvalds 已提交
1995

1996
	pr_debug("lec_addr_delete\n");
L
Linus Torvalds 已提交
1997
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
1998
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1999
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
2000 2001 2002
			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
			    && (permanent ||
				!(entry->flags & LEC_PERMANENT_FLAG))) {
L
Linus Torvalds 已提交
2003
				lec_arp_remove(priv, entry);
2004
				lec_arp_put(entry);
2005
			}
L
Linus Torvalds 已提交
2006
			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2007 2008 2009
			return 0;
		}
	}
L
Linus Torvalds 已提交
2010
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2011
	return -1;
L
Linus Torvalds 已提交
2012 2013 2014
}

/*
2015
 * Notifies:  Response to arp_request (atm_addr != NULL)
L
Linus Torvalds 已提交
2016 2017
 */
static void
2018 2019
lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
	       const unsigned char *atm_addr, unsigned long remoteflag,
2020
	       unsigned int targetless_le_arp)
L
Linus Torvalds 已提交
2021 2022
{
	unsigned long flags;
2023
	struct hlist_node *node, *next;
2024 2025
	struct lec_arp_table *entry, *tmp;
	int i;
L
Linus Torvalds 已提交
2026

2027 2028
	pr_debug("lec:%s", (targetless_le_arp) ? "targetless " : " ");
	pr_debug("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
2029 2030
		mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
		mac_addr[4], mac_addr[5]);
L
Linus Torvalds 已提交
2031 2032

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2033 2034 2035 2036 2037 2038
	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
				 */
2039 2040 2041 2042
	if (!hlist_empty(&priv->lec_arp_empty_ones)) {
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
			if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
				hlist_del(&entry->next);
2043
				del_timer(&entry->timer);
2044 2045 2046 2047 2048 2049 2050 2051 2052
				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);
2053
					lec_arp_put(entry);
2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
					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;
2065
				pr_debug("After update\n");
2066 2067
				dump_arp_table(priv);
				goto out;
2068 2069 2070
			}
		}
	}
2071

2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083
	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++) {
2084
		hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) {
2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
			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;
2107
		send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
2108
	}
2109
	pr_debug("After update2\n");
2110
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2111 2112 2113 2114 2115
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

/*
2116
 * Notifies: Vcc setup ready
L
Linus Torvalds 已提交
2117 2118
 */
static void
2119
lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data,
2120 2121
	      struct atm_vcc *vcc,
	      void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
L
Linus Torvalds 已提交
2122 2123
{
	unsigned long flags;
2124
	struct hlist_node *node;
2125 2126
	struct lec_arp_table *entry;
	int i, found_entry = 0;
L
Linus Torvalds 已提交
2127 2128

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2129 2130
	if (ioc_data->receive == 2) {
		/* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
L
Linus Torvalds 已提交
2131

2132
		pr_debug("LEC_ARP: Attaching mcast forward\n");
L
Linus Torvalds 已提交
2133
#if 0
2134 2135 2136
		entry = lec_arp_find(priv, bus_mac);
		if (!entry) {
			printk("LEC_ARP: Multicast entry not found!\n");
L
Linus Torvalds 已提交
2137
			goto out;
2138 2139 2140 2141
		}
		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
		entry->recv_vcc = vcc;
		entry->old_recv_push = old_push;
L
Linus Torvalds 已提交
2142
#endif
2143 2144
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2145
			goto out;
2146 2147 2148 2149
		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;
2150
		hlist_add_head(&entry->next, &priv->mcast_fwds);
2151 2152 2153 2154 2155 2156
		goto out;
	} else if (ioc_data->receive == 1) {
		/*
		 * Vcc which we don't want to make default vcc,
		 * attach it anyway.
		 */
2157
		pr_debug
2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
		    ("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]);
		entry = make_entry(priv, bus_mac);
		if (entry == NULL)
L
Linus Torvalds 已提交
2172
			goto out;
2173 2174 2175 2176 2177 2178 2179
		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;
2180
		hlist_add_head(&entry->next, &priv->lec_no_forward);
2181
		add_timer(&entry->timer);
L
Linus Torvalds 已提交
2182 2183
		dump_arp_table(priv);
		goto out;
2184
	}
2185
	pr_debug
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198
	    ("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]);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2199
		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
2200 2201 2202
			if (memcmp
			    (ioc_data->atm_addr, entry->atm_addr,
			     ATM_ESA_LEN) == 0) {
2203 2204
				pr_debug("LEC_ARP: Attaching data direct\n");
				pr_debug("Currently -> Vcc: %d, Rvcc:%d\n",
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220
					entry->vcc ? entry->vcc->vci : 0,
					entry->recv_vcc ? entry->recv_vcc->
					vci : 0);
				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 已提交
2221
#if 0
2222 2223 2224 2225
						send_to_lecd(priv, l_flush_xmt,
							     NULL,
							     entry->atm_addr,
							     NULL);
L
Linus Torvalds 已提交
2226
#endif
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245
					}
				} 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) {
2246
		pr_debug("After vcc was added\n");
2247
		dump_arp_table(priv);
L
Linus Torvalds 已提交
2248
		goto out;
2249 2250 2251 2252 2253 2254 2255
	}
	/*
	 * Not found, snatch address from first data packet that arrives
	 * from this vcc
	 */
	entry = make_entry(priv, bus_mac);
	if (!entry)
L
Linus Torvalds 已提交
2256
		goto out;
2257 2258 2259 2260 2261
	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;
2262
	hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
2263 2264 2265
	entry->timer.expires = jiffies + priv->vcc_timeout_period;
	entry->timer.function = lec_arp_expire_vcc;
	add_timer(&entry->timer);
2266
	pr_debug("After vcc was added\n");
L
Linus Torvalds 已提交
2267 2268 2269 2270 2271
	dump_arp_table(priv);
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

2272
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
L
Linus Torvalds 已提交
2273 2274
{
	unsigned long flags;
2275
	struct hlist_node *node;
2276 2277
	struct lec_arp_table *entry;
	int i;
L
Linus Torvalds 已提交
2278

2279
	pr_debug("LEC:lec_flush_complete %lx\n", tran_id);
2280
restart:
2281 2282
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2283
		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
2284 2285 2286
			if (entry->flush_tran_id == tran_id
			    && entry->status == ESI_FLUSH_PENDING) {
				struct sk_buff *skb;
2287
				struct atm_vcc *vcc = entry->vcc;
2288

2289 2290 2291
				lec_arp_hold(entry);
				spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
				while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
2292
					lec_send(vcc, skb);
2293
				entry->last_used = jiffies;
2294
				entry->status = ESI_FORWARD_DIRECT;
2295
				lec_arp_put(entry);
2296
				pr_debug("LEC_ARP: Flushed\n");
2297
				goto restart;
2298 2299 2300
			}
		}
	}
L
Linus Torvalds 已提交
2301
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2302
	dump_arp_table(priv);
L
Linus Torvalds 已提交
2303 2304 2305 2306
}

static void
lec_set_flush_tran_id(struct lec_priv *priv,
2307
		      const unsigned char *atm_addr, unsigned long tran_id)
L
Linus Torvalds 已提交
2308 2309
{
	unsigned long flags;
2310
	struct hlist_node *node;
2311 2312
	struct lec_arp_table *entry;
	int i;
L
Linus Torvalds 已提交
2313 2314

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2315
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
2316
		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
2317 2318
			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
				entry->flush_tran_id = tran_id;
2319
				pr_debug("Set flush transaction id to %lx for %p\n",
2320
					tran_id, entry);
2321
			}
2322
		}
L
Linus Torvalds 已提交
2323 2324 2325
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}

2326
static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
L
Linus Torvalds 已提交
2327 2328
{
	unsigned long flags;
2329 2330 2331 2332
	unsigned char mac_addr[] = {
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
	};
	struct lec_arp_table *to_add;
L
Linus Torvalds 已提交
2333 2334
	struct lec_vcc_priv *vpriv;
	int err = 0;
2335

L
Linus Torvalds 已提交
2336 2337 2338 2339 2340
	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
		return -ENOMEM;
	vpriv->xoff = 0;
	vpriv->old_pop = vcc->pop;
	vcc->user_back = vpriv;
2341
	vcc->pop = lec_pop;
L
Linus Torvalds 已提交
2342
	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2343 2344
	to_add = make_entry(priv, mac_addr);
	if (!to_add) {
L
Linus Torvalds 已提交
2345 2346
		vcc->pop = vpriv->old_pop;
		kfree(vpriv);
2347
		err = -ENOMEM;
L
Linus Torvalds 已提交
2348
		goto out;
2349 2350 2351 2352 2353 2354 2355 2356 2357
	}
	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 已提交
2358 2359
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2360
	return err;
L
Linus Torvalds 已提交
2361 2362
}

2363
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
L
Linus Torvalds 已提交
2364 2365
{
	unsigned long flags;
2366 2367
	struct hlist_node *node, *next;
	struct lec_arp_table *entry;
2368
	int i;
L
Linus Torvalds 已提交
2369

2370
	pr_debug("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
2371
	dump_arp_table(priv);
2372

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

2375
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2376
		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
2377 2378
			if (vcc == entry->vcc) {
				lec_arp_remove(priv, entry);
2379
				lec_arp_put(entry);
2380 2381 2382 2383 2384 2385 2386
				if (priv->mcast_vcc == vcc) {
					priv->mcast_vcc = NULL;
				}
			}
		}
	}

2387 2388
	hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
		if (entry->vcc == vcc) {
2389 2390
			lec_arp_clear_vccs(entry);
			del_timer(&entry->timer);
2391
			hlist_del(&entry->next);
2392
			lec_arp_put(entry);
2393 2394 2395
		}
	}

2396
	hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
2397 2398 2399
		if (entry->recv_vcc == vcc) {
			lec_arp_clear_vccs(entry);
			del_timer(&entry->timer);
2400
			hlist_del(&entry->next);
2401
			lec_arp_put(entry);
2402 2403 2404
		}
	}

2405
	hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
2406 2407 2408
		if (entry->recv_vcc == vcc) {
			lec_arp_clear_vccs(entry);
			/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
2409
			hlist_del(&entry->next);
2410
			lec_arp_put(entry);
2411 2412
		}
	}
L
Linus Torvalds 已提交
2413 2414 2415 2416 2417 2418 2419

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

static void
lec_arp_check_empties(struct lec_priv *priv,
2420
		      struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
2421
{
2422
	unsigned long flags;
2423 2424
	struct hlist_node *node, *next;
	struct lec_arp_table *entry, *tmp;
2425 2426
	struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
	unsigned char *src;
L
Linus Torvalds 已提交
2427
#ifdef CONFIG_TR
2428
	struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
L
Linus Torvalds 已提交
2429

2430 2431 2432
	if (priv->is_trdev)
		src = tr_hdr->h_source;
	else
L
Linus Torvalds 已提交
2433
#endif
2434
		src = hdr->h_source;
L
Linus Torvalds 已提交
2435 2436

	spin_lock_irqsave(&priv->lec_arp_lock, flags);
2437 2438 2439 2440 2441 2442 2443 2444 2445
	hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
		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 */
			if ((tmp = lec_arp_find(priv, src))) {
				lec_arp_remove(priv, tmp);
2446
				lec_arp_put(tmp);
2447 2448 2449 2450
			}
			hlist_del(&entry->next);
			lec_arp_add(priv, entry);
			goto out;
2451 2452
		}
	}
2453
	pr_debug("LEC_ARP: Arp_check_empties: entry not found!\n");
L
Linus Torvalds 已提交
2454 2455 2456
out:
	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
2457

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