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 const char *lec_arp_get_status_string(unsigned char status)
L
Linus Torvalds 已提交
939
{
940
	static const char *const lec_arp_status_string[] = {
L
Linus Torvalds 已提交
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
		"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
	static const char lec_banner[] =
	    "Itf  MAC          ATM destination"
1126 1127
	    "                          Status            Flags "
	    "VPI/VCI Recv VPI/VCI\n";
L
Linus Torvalds 已提交
1128

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

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

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

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

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

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

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

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

	return err;
}

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

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

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

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

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

	remove_proc_entry("lec", atm_proc_root);

	deregister_atm_ioctl(&lane_ioctl_ops);

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

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

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

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

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

		*sizeoftlvs = table->sizeoftlvs;

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

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

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

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

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

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

	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
	if (skb == NULL)
		return 0;
	skb->len = sizeoftlvs;
1316
	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
1317 1318 1319 1320 1321 1322 1323 1324
	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 已提交
1325 1326 1327 1328 1329 1330
}

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

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

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

1351
	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
1352 1353 1354
	if (entry->tlvs == NULL)
		return;
	entry->sizeoftlvs = sizeoftlvs;
L
Linus Torvalds 已提交
1355 1356
#endif
#if 0
1357 1358 1359 1360 1361 1362
	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 已提交
1363 1364
#endif

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

/*
 * 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
1388
#define pr_debug(format,args...)
L
Linus Torvalds 已提交
1389
/*
1390
#define pr_debug printk
L
Linus Torvalds 已提交
1391 1392 1393 1394 1395 1396
*/
#endif
#define DEBUG_ARP_TABLE 0

#define LEC_ARP_REFRESH_INTERVAL (3*HZ)

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

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

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

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

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

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

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

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

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

1459
	pr_debug("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1460 1461 1462
		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 已提交
1463 1464 1465 1466 1467
}

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

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

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

1482
	/* If this is the only MAC connected to this VCC, also tear down the VCC */
1483 1484 1485 1486
	if (to_remove->status >= ESI_FLUSH_PENDING) {
		/*
		 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
		 */
1487 1488 1489 1490
		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) {
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500
					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? */

1501
	pr_debug("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1502 1503 1504 1505
		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 已提交
1506 1507 1508
}

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

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

	printk("Dump %p:\n", priv);
	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1536 1537 1538
		hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) {
			offset = 0;
			offset += sprintf(buf, "%d: %p\n", i, rulla);
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 1564
			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));
1565
			printk("%s\n", buf);
1566 1567
		}
	}
1568 1569

	if (!hlist_empty(&priv->lec_no_forward))
1570
		printk("No forward\n");
1571
	hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
		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));
1595
		printk("%s\n", buf);
1596
	}
1597 1598

	if (!hlist_empty(&priv->lec_arp_empty_ones))
1599
		printk("Empty ones\n");
1600
	hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
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 1626
		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);
	}

1627
	if (!hlist_empty(&priv->mcast_fwds))
1628
		printk("Multicast Forward VCCs\n");
1629
	hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
		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));
1653
		printk("%s\n", buf);
1654
	}
L
Linus Torvalds 已提交
1655 1656

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

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

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

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

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

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

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

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

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

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

1727 1728 1729 1730
	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;
1731 1732 1733
		}
	}
	return NULL;
L
Linus Torvalds 已提交
1734 1735
}

1736
static struct lec_arp_table *make_entry(struct lec_priv *priv,
1737
					const unsigned char *mac_addr)
L
Linus Torvalds 已提交
1738
{
1739 1740 1741 1742 1743 1744 1745 1746
	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);
1747
	INIT_HLIST_NODE(&to_return->next);
1748 1749
	setup_timer(&to_return->timer, lec_arp_expire_arp,
			(unsigned long)to_return);
1750 1751 1752
	to_return->last_used = jiffies;
	to_return->priv = priv;
	skb_queue_head_init(&to_return->tx_wait);
1753
	atomic_set(&to_return->usage, 1);
1754
	return to_return;
L
Linus Torvalds 已提交
1755 1756
}

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

	entry = (struct lec_arp_table *)data;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2028 2029
	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",
2030 2031
		mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
		mac_addr[4], mac_addr[5]);
L
Linus Torvalds 已提交
2032 2033

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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