Ok, there's a test13-pre6 out there now, which does a partial sync with
[davej-history.git] / net / atm / lec.c
blob6b68d7995952509dad468b80bd655133f19a074e
1 /*
2 * lec.c: Lan Emulation driver
3 * Marko Kiiskila carnil@cs.tut.fi
5 */
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/bitops.h>
11 /* We are ethernet device */
12 #include <linux/if_ether.h>
13 #include <linux/netdevice.h>
14 #include <linux/etherdevice.h>
15 #include <net/sock.h>
16 #include <linux/skbuff.h>
17 #include <linux/ip.h>
18 #include <asm/byteorder.h>
19 #include <asm/uaccess.h>
20 #include <net/arp.h>
21 #include <net/dst.h>
22 #include <linux/proc_fs.h>
24 /* TokenRing if needed */
25 #ifdef CONFIG_TR
26 #include <linux/trdevice.h>
27 #endif
29 /* And atm device */
30 #include <linux/atmdev.h>
31 #include <linux/atmlec.h>
33 /* Proxy LEC knows about bridging */
34 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
35 #include <linux/if_bridge.h>
36 #include "../bridge/br_private.h"
37 static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
38 #endif
40 /* Modular too */
41 #include <linux/module.h>
43 #include "lec.h"
44 #include "lec_arpc.h"
45 #include "resources.h" /* for bind_vcc() */
47 #if 0
48 #define DPRINTK printk
49 #else
50 #define DPRINTK(format,args...)
51 #endif
53 #define DUMP_PACKETS 0 /* 0 = None,
54 * 1 = 30 first bytes
55 * 2 = Whole packet
58 #define LEC_UNRES_QUE_LEN 8 /* number of tx packets to queue for a
59 single destination while waiting for SVC */
61 static int lec_open(struct net_device *dev);
62 static int lec_send_packet(struct sk_buff *skb, struct net_device *dev);
63 static int lec_close(struct net_device *dev);
64 static struct net_device_stats *lec_get_stats(struct net_device *dev);
65 static void lec_init(struct net_device *dev);
66 static __inline__ struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
67 unsigned char *mac_addr);
68 static __inline__ int lec_arp_remove(struct lec_arp_table **lec_arp_tables,
69 struct lec_arp_table *to_remove);
70 /* LANE2 functions */
71 static void lane2_associate_ind (struct net_device *dev, u8 *mac_address,
72 u8 *tlvs, u32 sizeoftlvs);
73 static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
74 u8 **tlvs, u32 *sizeoftlvs);
75 static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
76 u8 *tlvs, u32 sizeoftlvs);
78 static struct lane2_ops lane2_ops = {
79 lane2_resolve, /* resolve, spec 3.1.3 */
80 lane2_associate_req, /* associate_req, spec 3.1.4 */
81 NULL /* associate indicator, spec 3.1.5 */
84 static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
86 /* Device structures */
87 static struct net_device *dev_lec[MAX_LEC_ITF];
89 /* This will be called from proc.c via function pointer */
90 struct net_device **get_dev_lec (void) {
91 return &dev_lec[0];
94 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
95 static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
97 struct ethhdr *eth;
98 char *buff;
99 struct lec_priv *priv;
101 /* Check if this is a BPDU. If so, ask zeppelin to send
102 * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
103 * as the Config BPDU has */
104 eth = (struct ethhdr *)skb->data;
105 buff = skb->data + skb->dev->hard_header_len;
106 if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
107 struct sk_buff *skb2;
108 struct atmlec_msg *mesg;
110 skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
111 if (skb2 == NULL) return;
112 skb2->len = sizeof(struct atmlec_msg);
113 mesg = (struct atmlec_msg *)skb2->data;
114 mesg->type = l_topology_change;
115 buff += 4;
116 mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */
118 priv = (struct lec_priv *)dev->priv;
119 atm_force_charge(priv->lecd, skb2->truesize);
120 skb_queue_tail(&priv->lecd->recvq, skb2);
121 wake_up(&priv->lecd->sleep);
124 return;
126 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
129 * Modelled after tr_type_trans
130 * All multicast and ARE or STE frames go to BUS.
131 * Non source routed frames go by destination address.
132 * Last hop source routed frames go by destination address.
133 * Not last hop source routed frames go by _next_ route descriptor.
134 * Returns pointer to destination MAC address or fills in rdesc
135 * and returns NULL.
137 #ifdef CONFIG_TR
138 unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
140 struct trh_hdr *trh;
141 int riflen, num_rdsc;
143 trh = (struct trh_hdr *)packet;
144 if (trh->daddr[0] & (uint8_t)0x80)
145 return bus_mac; /* multicast */
147 if (trh->saddr[0] & TR_RII) {
148 riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
149 if ((ntohs(trh->rcf) >> 13) != 0)
150 return bus_mac; /* ARE or STE */
152 else
153 return trh->daddr; /* not source routed */
155 if (riflen < 6)
156 return trh->daddr; /* last hop, source routed */
158 /* riflen is 6 or more, packet has more than one route descriptor */
159 num_rdsc = (riflen/2) - 1;
160 memset(rdesc, 0, ETH_ALEN);
161 /* offset 4 comes from LAN destination field in LE control frames */
162 if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT))
163 memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t));
164 else {
165 memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
166 rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
169 return NULL;
171 #endif /* CONFIG_TR */
174 * Open/initialize the netdevice. This is called (in the current kernel)
175 * sometime after booting when the 'ifconfig' program is run.
177 * This routine should set everything up anew at each open, even
178 * registers that "should" only need to be set once at boot, so that
179 * there is non-reboot way to recover if something goes wrong.
182 static int
183 lec_open(struct net_device *dev)
185 struct lec_priv *priv = (struct lec_priv *)dev->priv;
187 netif_start_queue(dev);
188 memset(&priv->stats,0,sizeof(struct net_device_stats));
190 return 0;
193 static int
194 lec_send_packet(struct sk_buff *skb, struct net_device *dev)
196 struct sk_buff *skb2;
197 struct lec_priv *priv = (struct lec_priv *)dev->priv;
198 struct lecdatahdr_8023 *lec_h;
199 struct atm_vcc *send_vcc;
200 struct lec_arp_table *entry;
201 unsigned char *nb, *dst;
202 #ifdef CONFIG_TR
203 unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */
204 #endif
205 int is_rdesc;
206 #if DUMP_PACKETS > 0
207 char buf[300];
208 int i=0;
209 #endif /* DUMP_PACKETS >0 */
211 DPRINTK("Lec_send_packet called\n");
212 if (!priv->lecd) {
213 printk("%s:No lecd attached\n",dev->name);
214 priv->stats.tx_errors++;
215 netif_stop_queue(dev);
216 return -EUNATCH;
219 DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
220 (long)skb->head, (long)skb->data, (long)skb->tail,
221 (long)skb->end);
222 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
223 if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
224 lec_handle_bridge(skb, dev);
225 #endif
227 /* Make sure we have room for lec_id */
228 if (skb_headroom(skb) < 2) {
230 DPRINTK("lec_send_packet: reallocating skb\n");
231 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
232 kfree_skb(skb);
233 if (skb2 == NULL) return 0;
234 skb = skb2;
236 skb_push(skb, 2);
238 /* Put le header to place, works for TokenRing too */
239 lec_h = (struct lecdatahdr_8023*)skb->data;
240 lec_h->le_header = htons(priv->lecid);
242 #ifdef CONFIG_TR
243 /* Ugly. Use this to realign Token Ring packets for
244 * e.g. PCA-200E driver. */
245 if (priv->is_trdev) {
246 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
247 kfree_skb(skb);
248 if (skb2 == NULL) return 0;
249 skb = skb2;
251 #endif
253 #if DUMP_PACKETS > 0
254 printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
255 skb->len, priv->lecid);
256 #if DUMP_PACKETS >= 2
257 for(i=0;i<skb->len && i <99;i++) {
258 sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]);
260 #elif DUMP_PACKETS >= 1
261 for(i=0;i<skb->len && i < 30;i++) {
262 sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]);
264 #endif /* DUMP_PACKETS >= 1 */
265 if (i==skb->len)
266 printk("%s\n",buf);
267 else
268 printk("%s...\n",buf);
269 #endif /* DUMP_PACKETS > 0 */
271 /* Minimum ethernet-frame size */
272 if (skb->len <62) {
273 if (skb->truesize < 62) {
274 printk("%s:data packet %d / %d\n",
275 dev->name,
276 skb->len,skb->truesize);
277 nb=(unsigned char*)kmalloc(64, GFP_ATOMIC);
278 memcpy(nb,skb->data,skb->len);
279 kfree(skb->head);
280 skb->head = skb->data = nb;
281 skb->tail = nb+62;
282 skb->end = nb+64;
283 skb->len=62;
284 skb->truesize = 64;
285 } else {
286 skb->len = 62;
290 /* Send to right vcc */
291 is_rdesc = 0;
292 dst = lec_h->h_dest;
293 #ifdef CONFIG_TR
294 if (priv->is_trdev) {
295 dst = get_tr_dst(skb->data+2, rdesc);
296 if (dst == NULL) {
297 dst = rdesc;
298 is_rdesc = 1;
301 #endif
302 entry = NULL;
303 send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
304 DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
305 send_vcc, send_vcc?send_vcc->flags:0, entry);
306 if (!send_vcc || !test_bit(ATM_VF_READY,&send_vcc->flags)) {
307 if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
308 DPRINTK("%s:lec_send_packet: queuing packet, ", dev->name);
309 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
310 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
311 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
312 skb_queue_tail(&entry->tx_wait, skb);
313 } else {
314 DPRINTK("%s:lec_send_packet: tx queue full or no arp entry, dropping, ", dev->name);
315 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
316 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
317 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
318 priv->stats.tx_dropped++;
319 dev_kfree_skb(skb);
321 return 0;
324 #if DUMP_PACKETS > 0
325 printk("%s:sending to vpi:%d vci:%d\n", dev->name,
326 send_vcc->vpi, send_vcc->vci);
327 #endif /* DUMP_PACKETS > 0 */
329 while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
330 DPRINTK("lec.c: emptying tx queue, ");
331 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
332 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
333 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
334 ATM_SKB(skb2)->vcc = send_vcc;
335 ATM_SKB(skb2)->iovcnt = 0;
336 ATM_SKB(skb2)->atm_options = send_vcc->atm_options;
337 DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name,
338 send_vcc->vpi, send_vcc->vci);
339 if (atm_may_send(send_vcc, skb2->len)) {
340 atomic_add(skb2->truesize, &send_vcc->tx_inuse);
341 priv->stats.tx_packets++;
342 priv->stats.tx_bytes += skb2->len;
343 send_vcc->send(send_vcc, skb2);
344 } else {
345 priv->stats.tx_dropped++;
346 dev_kfree_skb(skb2);
350 ATM_SKB(skb)->vcc = send_vcc;
351 ATM_SKB(skb)->iovcnt = 0;
352 ATM_SKB(skb)->atm_options = send_vcc->atm_options;
353 if (atm_may_send(send_vcc, skb->len)) {
354 atomic_add(skb->truesize, &send_vcc->tx_inuse);
355 priv->stats.tx_packets++;
356 priv->stats.tx_bytes += skb->len;
357 send_vcc->send(send_vcc, skb);
358 } else {
359 priv->stats.tx_dropped++;
360 dev_kfree_skb(skb);
363 #if 0
364 /* Should we wait for card's device driver to notify us? */
365 dev->tbusy=0;
366 #endif
367 return 0;
370 /* The inverse routine to net_open(). */
371 static int
372 lec_close(struct net_device *dev)
374 netif_stop_queue(dev);
375 return 0;
379 * Get the current statistics.
380 * This may be called with the card open or closed.
382 static struct net_device_stats *
383 lec_get_stats(struct net_device *dev)
385 return &((struct lec_priv *)dev->priv)->stats;
388 static int
389 lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
391 struct net_device *dev = (struct net_device*)vcc->proto_data;
392 struct lec_priv *priv = (struct lec_priv*)dev->priv;
393 struct atmlec_msg *mesg;
394 struct lec_arp_table *entry;
395 int i;
396 char *tmp; /* FIXME */
398 atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
399 mesg = (struct atmlec_msg *)skb->data;
400 tmp = skb->data;
401 tmp += sizeof(struct atmlec_msg);
402 DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
403 switch(mesg->type) {
404 case l_set_mac_addr:
405 for (i=0;i<6;i++) {
406 dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
408 break;
409 case l_del_mac_addr:
410 for(i=0;i<6;i++) {
411 dev->dev_addr[i] = 0;
413 break;
414 case l_addr_delete:
415 lec_addr_delete(priv, mesg->content.normal.atm_addr,
416 mesg->content.normal.flag);
417 break;
418 case l_topology_change:
419 priv->topology_change = mesg->content.normal.flag;
420 break;
421 case l_flush_complete:
422 lec_flush_complete(priv, mesg->content.normal.flag);
423 break;
424 case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
425 entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
426 lec_arp_remove(priv->lec_arp_tables, entry);
428 if (mesg->content.normal.no_source_le_narp)
429 break;
430 /* FALL THROUGH */
431 case l_arp_update:
432 lec_arp_update(priv, mesg->content.normal.mac_addr,
433 mesg->content.normal.atm_addr,
434 mesg->content.normal.flag,
435 mesg->content.normal.targetless_le_arp);
436 DPRINTK("lec: in l_arp_update\n");
437 if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */
438 DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n", mesg->sizeoftlvs);
439 lane2_associate_ind(dev,
440 mesg->content.normal.mac_addr,
441 tmp, mesg->sizeoftlvs);
443 break;
444 case l_config:
445 priv->maximum_unknown_frame_count =
446 mesg->content.config.maximum_unknown_frame_count;
447 priv->max_unknown_frame_time =
448 (mesg->content.config.max_unknown_frame_time*HZ);
449 priv->max_retry_count =
450 mesg->content.config.max_retry_count;
451 priv->aging_time = (mesg->content.config.aging_time*HZ);
452 priv->forward_delay_time =
453 (mesg->content.config.forward_delay_time*HZ);
454 priv->arp_response_time =
455 (mesg->content.config.arp_response_time*HZ);
456 priv->flush_timeout = (mesg->content.config.flush_timeout*HZ);
457 priv->path_switching_delay =
458 (mesg->content.config.path_switching_delay*HZ);
459 priv->lane_version = mesg->content.config.lane_version; /* LANE2 */
460 priv->lane2_ops = NULL;
461 if (priv->lane_version > 1)
462 priv->lane2_ops = &lane2_ops;
463 if (dev->change_mtu(dev, mesg->content.config.mtu))
464 printk("%s: change_mtu to %d failed\n", dev->name,
465 mesg->content.config.mtu);
466 priv->is_proxy = mesg->content.config.is_proxy;
467 break;
468 case l_flush_tran_id:
469 lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
470 mesg->content.normal.flag);
471 break;
472 case l_set_lecid:
473 priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag);
474 break;
475 case l_should_bridge: {
476 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
477 struct net_bridge_fdb_entry *f;
479 DPRINTK("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
480 dev->name,
481 mesg->content.proxy.mac_addr[0], mesg->content.proxy.mac_addr[1],
482 mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3],
483 mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]);
485 if (br_fdb_get_hook == NULL || dev->br_port == NULL)
486 break;
488 f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr);
489 if (f != NULL &&
490 f->dst->dev != dev &&
491 f->dst->state == BR_STATE_FORWARDING) {
492 /* hit from bridge table, send LE_ARP_RESPONSE */
493 struct sk_buff *skb2;
495 DPRINTK("%s: entry found, responding to zeppelin\n", dev->name);
496 skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
497 if (skb2 == NULL) {
498 br_fdb_put_hook(f);
499 break;
501 skb2->len = sizeof(struct atmlec_msg);
502 memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
503 atm_force_charge(priv->lecd, skb2->truesize);
504 skb_queue_tail(&priv->lecd->recvq, skb2);
505 wake_up(&priv->lecd->sleep);
507 if (f != NULL) br_fdb_put_hook(f);
508 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
510 break;
511 default:
512 printk("%s: Unknown message type %d\n", dev->name, mesg->type);
513 dev_kfree_skb(skb);
514 return -EINVAL;
516 dev_kfree_skb(skb);
517 return 0;
520 static void
521 lec_atm_close(struct atm_vcc *vcc)
523 struct sk_buff *skb;
524 struct net_device *dev = (struct net_device *)vcc->proto_data;
525 struct lec_priv *priv = (struct lec_priv *)dev->priv;
527 priv->lecd = NULL;
528 /* Do something needful? */
530 netif_stop_queue(dev);
531 lec_arp_destroy(priv);
533 if (skb_peek(&vcc->recvq))
534 printk("%s lec_atm_close: closing with messages pending\n",
535 dev->name);
536 while ((skb = skb_dequeue(&vcc->recvq))) {
537 atm_return(vcc, skb->truesize);
538 dev_kfree_skb(skb);
541 printk("%s: Shut down!\n", dev->name);
542 MOD_DEC_USE_COUNT;
545 static struct atmdev_ops lecdev_ops = {
546 close: lec_atm_close,
547 send: lec_atm_send
550 static struct atm_dev lecatm_dev = {
551 &lecdev_ops,
552 NULL, /*PHY*/
553 "lec", /*type*/
554 999, /*dummy device number*/
555 NULL,NULL, /*no VCCs*/
556 NULL,NULL, /*no data*/
557 { 0 }, /*no flags*/
558 NULL, /* no local address*/
559 { 0 } /*no ESI or rest of the atm_dev struct things*/
563 * LANE2: new argument struct sk_buff *data contains
564 * the LE_ARP based TLVs introduced in the LANE2 spec
566 int
567 send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
568 unsigned char *mac_addr, unsigned char *atm_addr,
569 struct sk_buff *data)
571 struct sk_buff *skb;
572 struct atmlec_msg *mesg;
574 if (!priv || !priv->lecd) {
575 return -1;
577 skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
578 if (!skb)
579 return -1;
580 skb->len = sizeof(struct atmlec_msg);
581 mesg = (struct atmlec_msg *)skb->data;
582 memset(mesg, 0, sizeof(struct atmlec_msg));
583 mesg->type = type;
584 if (data != NULL)
585 mesg->sizeoftlvs = data->len;
586 if (mac_addr)
587 memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
588 else
589 mesg->content.normal.targetless_le_arp = 1;
590 if (atm_addr)
591 memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
593 atm_force_charge(priv->lecd, skb->truesize);
594 skb_queue_tail(&priv->lecd->recvq, skb);
595 wake_up(&priv->lecd->sleep);
597 if (data != NULL) {
598 DPRINTK("lec: about to send %d bytes of data\n", data->len);
599 atm_force_charge(priv->lecd, data->truesize);
600 skb_queue_tail(&priv->lecd->recvq, data);
601 wake_up(&priv->lecd->sleep);
604 return 0;
607 /* shamelessly stolen from drivers/net/net_init.c */
608 static int lec_change_mtu(struct net_device *dev, int new_mtu)
610 if ((new_mtu < 68) || (new_mtu > 18190))
611 return -EINVAL;
612 dev->mtu = new_mtu;
613 return 0;
616 static void
617 lec_init(struct net_device *dev)
619 dev->change_mtu = lec_change_mtu;
620 dev->open = lec_open;
621 dev->stop = lec_close;
622 dev->hard_start_xmit = lec_send_packet;
624 dev->get_stats = lec_get_stats;
625 dev->set_multicast_list = NULL;
626 dev->do_ioctl = NULL;
627 printk("%s: Initialized!\n",dev->name);
628 return;
631 static unsigned char lec_ctrl_magic[] = {
632 0xff,
633 0x00,
634 0x01,
635 0x01 };
637 void
638 lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
640 struct net_device *dev = (struct net_device *)vcc->proto_data;
641 struct lec_priv *priv = (struct lec_priv *)dev->priv;
643 #if DUMP_PACKETS >0
644 int i=0;
645 char buf[300];
647 printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
648 vcc->vpi, vcc->vci);
649 #endif
650 if (!skb) {
651 DPRINTK("%s: null skb\n",dev->name);
652 lec_vcc_close(priv, vcc);
653 return;
655 #if DUMP_PACKETS > 0
656 printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
657 skb->len, priv->lecid);
658 #if DUMP_PACKETS >= 2
659 for(i=0;i<skb->len && i <99;i++) {
660 sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]);
662 #elif DUMP_PACKETS >= 1
663 for(i=0;i<skb->len && i < 30;i++) {
664 sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]);
666 #endif /* DUMP_PACKETS >= 1 */
667 if (i==skb->len)
668 printk("%s\n",buf);
669 else
670 printk("%s...\n",buf);
671 #endif /* DUMP_PACKETS > 0 */
672 if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
673 DPRINTK("%s: To daemon\n",dev->name);
674 skb_queue_tail(&vcc->recvq, skb);
675 wake_up(&vcc->sleep);
676 } else { /* Data frame, queue to protocol handlers */
677 unsigned char *dst;
679 atm_return(vcc,skb->truesize);
680 if (*(uint16_t *)skb->data == htons(priv->lecid) ||
681 !priv->lecd) {
682 /* Probably looping back, or if lecd is missing,
683 lecd has gone down */
684 DPRINTK("Ignoring loopback frame...\n");
685 dev_kfree_skb(skb);
686 return;
688 #ifdef CONFIG_TR
689 if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
690 else
691 #endif
692 dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
694 if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */
695 !priv->is_proxy && /* Proxy wants all the packets */
696 memcmp(dst, dev->dev_addr, dev->addr_len)) {
697 dev_kfree_skb(skb);
698 return;
700 if (priv->lec_arp_empty_ones) {
701 lec_arp_check_empties(priv, vcc, skb);
703 skb->dev = dev;
704 skb->data += 2; /* skip lec_id */
705 #ifdef CONFIG_TR
706 if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
707 else
708 #endif
709 skb->protocol = eth_type_trans(skb, dev);
710 priv->stats.rx_packets++;
711 priv->stats.rx_bytes += skb->len;
712 netif_rx(skb);
716 int
717 lec_vcc_attach(struct atm_vcc *vcc, void *arg)
719 int bytes_left;
720 struct atmlec_ioc ioc_data;
722 /* Lecd must be up in this case */
723 bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
724 if (bytes_left != 0) {
725 printk("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
726 bytes_left);
728 if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
729 !dev_lec[ioc_data.dev_num])
730 return -EINVAL;
731 lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
732 &ioc_data, vcc, vcc->push);
733 vcc->push = lec_push;
734 vcc->proto_data = dev_lec[ioc_data.dev_num];
735 return 0;
738 int
739 lec_mcast_attach(struct atm_vcc *vcc, int arg)
741 if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
742 return -EINVAL;
743 vcc->proto_data = dev_lec[arg];
744 return (lec_mcast_make((struct lec_priv*)dev_lec[arg]->priv, vcc));
747 /* Initialize device. */
748 int
749 lecd_attach(struct atm_vcc *vcc, int arg)
751 int i;
752 struct lec_priv *priv;
754 if (arg<0)
755 i = 0;
756 else
757 i = arg;
758 #ifdef CONFIG_TR
759 if (arg >= MAX_LEC_ITF)
760 return -EINVAL;
761 #else /* Reserve the top NUM_TR_DEVS for TR */
762 if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS))
763 return -EINVAL;
764 #endif
765 if (!dev_lec[i]) {
766 int is_trdev, size;
768 is_trdev = 0;
769 if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
770 is_trdev = 1;
772 size = sizeof(struct lec_priv);
773 #ifdef CONFIG_TR
774 if (is_trdev)
775 dev_lec[i] = prepare_trdev(NULL, size);
776 else
777 #endif
778 dev_lec[i] = prepare_etherdev(NULL, size);
779 if (!dev_lec[i])
780 return -ENOMEM;
782 priv = dev_lec[i]->priv;
783 priv->is_trdev = is_trdev;
784 sprintf(dev_lec[i]->name, "lec%d", i);
785 lec_init(dev_lec[i]);
786 publish_netdev(dev_lec[i]);
787 } else {
788 priv = dev_lec[i]->priv;
789 if (priv->lecd)
790 return -EADDRINUSE;
792 lec_arp_init(priv);
793 priv->itfnum = i; /* LANE2 addition */
794 priv->lecd = vcc;
795 bind_vcc(vcc, &lecatm_dev);
797 vcc->proto_data = dev_lec[i];
798 set_bit(ATM_VF_META,&vcc->flags);
799 set_bit(ATM_VF_READY,&vcc->flags);
801 /* Set default values to these variables */
802 priv->maximum_unknown_frame_count = 1;
803 priv->max_unknown_frame_time = (1*HZ);
804 priv->vcc_timeout_period = (1200*HZ);
805 priv->max_retry_count = 1;
806 priv->aging_time = (300*HZ);
807 priv->forward_delay_time = (15*HZ);
808 priv->topology_change = 0;
809 priv->arp_response_time = (1*HZ);
810 priv->flush_timeout = (4*HZ);
811 priv->path_switching_delay = (6*HZ);
813 if (dev_lec[i]->flags & IFF_UP) {
814 netif_start_queue(dev_lec[i]);
816 MOD_INC_USE_COUNT;
817 return i;
820 void atm_lane_init_ops(struct atm_lane_ops *ops)
822 ops->lecd_attach = lecd_attach;
823 ops->mcast_attach = lec_mcast_attach;
824 ops->vcc_attach = lec_vcc_attach;
825 ops->get_lecs = get_dev_lec;
827 printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
829 return;
832 #ifdef MODULE
833 int init_module(void)
835 extern struct atm_lane_ops atm_lane_ops;
837 atm_lane_init_ops(&atm_lane_ops);
839 return 0;
842 void cleanup_module(void)
844 int i;
845 extern struct atm_lane_ops atm_lane_ops;
846 struct lec_priv *priv;
848 if (MOD_IN_USE) {
849 printk(KERN_NOTICE "lec.c: module in use\n");
850 return;
853 atm_lane_ops.lecd_attach = NULL;
854 atm_lane_ops.mcast_attach = NULL;
855 atm_lane_ops.vcc_attach = NULL;
856 atm_lane_ops.get_lecs = NULL;
858 for (i = 0; i < MAX_LEC_ITF; i++) {
859 if (dev_lec[i] != NULL) {
860 priv = (struct lec_priv *)dev_lec[i]->priv;
861 unregister_netdev(dev_lec[i]);
862 kfree(dev_lec[i]);
863 dev_lec[i] = NULL;
867 return;
869 #endif /* MODULE */
872 * LANE2: 3.1.3, LE_RESOLVE.request
873 * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs.
874 * If sizeoftlvs == NULL the default TLVs associated with with this
875 * lec will be used.
876 * If dst_mac == NULL, targetless LE_ARP will be sent
878 static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
879 u8 **tlvs, u32 *sizeoftlvs)
881 struct lec_priv *priv = (struct lec_priv *)dev->priv;
882 struct lec_arp_table *table;
883 struct sk_buff *skb;
884 int retval;
886 if (force == 0) {
887 table = lec_arp_find(priv, dst_mac);
888 if(table == NULL)
889 return -1;
891 *tlvs = kmalloc(table->sizeoftlvs, GFP_KERNEL);
892 if (*tlvs == NULL)
893 return -1;
895 memcpy(*tlvs, table->tlvs, table->sizeoftlvs);
896 *sizeoftlvs = table->sizeoftlvs;
898 return 0;
901 if (sizeoftlvs == NULL)
902 retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
904 else {
905 skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
906 if (skb == NULL)
907 return -1;
908 skb->len = *sizeoftlvs;
909 memcpy(skb->data, *tlvs, *sizeoftlvs);
910 retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
912 return retval;
917 * LANE2: 3.1.4, LE_ASSOCIATE.request
918 * Associate the *tlvs with the *lan_dst address.
919 * Will overwrite any previous association
920 * Returns 1 for success, 0 for failure (out of memory)
923 static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
924 u8 *tlvs, u32 sizeoftlvs)
926 int retval;
927 struct sk_buff *skb;
928 struct lec_priv *priv = (struct lec_priv*)dev->priv;
930 if ( memcmp(lan_dst, dev->dev_addr, ETH_ALEN) != 0 )
931 return (0); /* not our mac address */
933 kfree(priv->tlvs); /* NULL if there was no previous association */
935 priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
936 if (priv->tlvs == NULL)
937 return (0);
938 priv->sizeoftlvs = sizeoftlvs;
939 memcpy(priv->tlvs, tlvs, sizeoftlvs);
941 skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
942 if (skb == NULL)
943 return 0;
944 skb->len = sizeoftlvs;
945 memcpy(skb->data, tlvs, sizeoftlvs);
946 retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
947 if (retval != 0)
948 printk("lec.c: lane2_associate_req() failed\n");
949 /* If the previous association has changed we must
950 * somehow notify other LANE entities about the change
952 return (1);
956 * LANE2: 3.1.5, LE_ASSOCIATE.indication
959 static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
960 u8 *tlvs, u32 sizeoftlvs)
962 #if 0
963 int i = 0;
964 #endif
965 struct lec_priv *priv = (struct lec_priv *)dev->priv;
966 #if 0 /* Why have the TLVs in LE_ARP entries since we do not use them? When you
967 uncomment this code, make sure the TLVs get freed when entry is killed */
968 struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
970 if (entry == NULL)
971 return; /* should not happen */
973 kfree(entry->tlvs);
975 entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
976 if (entry->tlvs == NULL)
977 return;
979 entry->sizeoftlvs = sizeoftlvs;
980 memcpy(entry->tlvs, tlvs, sizeoftlvs);
981 #endif
982 #if 0
983 printk("lec.c: lane2_associate_ind()\n");
984 printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
985 while (i < sizeoftlvs)
986 printk("%02x ", tlvs[i++]);
988 printk("\n");
989 #endif
991 /* tell MPOA about the TLVs we saw */
992 if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
993 priv->lane2_ops->associate_indicator(dev, mac_addr,
994 tlvs, sizeoftlvs);
996 return;
1000 * Here starts what used to lec_arpc.c
1002 * lec_arpc.c was added here when making
1003 * lane client modular. October 1997
1007 #include <linux/types.h>
1008 #include <linux/sched.h>
1009 #include <linux/timer.h>
1010 #include <asm/param.h>
1011 #include <asm/atomic.h>
1012 #include <linux/inetdevice.h>
1013 #include <net/route.h>
1016 #if 0
1017 #define DPRINTK(format,args...)
1019 #define DPRINTK printk
1021 #endif
1022 #define DEBUG_ARP_TABLE 0
1024 #define LEC_ARP_REFRESH_INTERVAL (3*HZ)
1026 static void lec_arp_check_expire(unsigned long data);
1027 static __inline__ void lec_arp_expire_arp(unsigned long data);
1028 void dump_arp_table(struct lec_priv *priv);
1031 * Arp table funcs
1034 #define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
1036 static __inline__ void
1037 lec_arp_lock(struct lec_priv *priv)
1039 atomic_inc(&priv->lec_arp_lock_var);
1042 static __inline__ void
1043 lec_arp_unlock(struct lec_priv *priv)
1045 atomic_dec(&priv->lec_arp_lock_var);
1049 * Initialization of arp-cache
1051 void
1052 lec_arp_init(struct lec_priv *priv)
1054 unsigned short i;
1056 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1057 priv->lec_arp_tables[i] = NULL;
1059 init_timer(&priv->lec_arp_timer);
1060 priv->lec_arp_timer.expires = jiffies+LEC_ARP_REFRESH_INTERVAL;
1061 priv->lec_arp_timer.data = (unsigned long)priv;
1062 priv->lec_arp_timer.function = lec_arp_check_expire;
1063 add_timer(&priv->lec_arp_timer);
1066 void
1067 lec_arp_clear_vccs(struct lec_arp_table *entry)
1069 if (entry->vcc) {
1070 entry->vcc->push = entry->old_push;
1071 #if 0 /* August 6, 1998 */
1072 set_bit(ATM_VF_RELEASED,&entry->vcc->flags);
1073 clear_bit(ATM_VF_READY,&entry->vcc->flags);
1074 entry->vcc->push(entry->vcc, NULL);
1075 #endif
1076 atm_async_release_vcc(entry->vcc, -EPIPE);
1077 entry->vcc = NULL;
1079 if (entry->recv_vcc) {
1080 entry->recv_vcc->push = entry->old_recv_push;
1081 #if 0
1082 set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags);
1083 clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
1084 entry->recv_vcc->push(entry->recv_vcc, NULL);
1085 #endif
1086 atm_async_release_vcc(entry->recv_vcc, -EPIPE);
1087 entry->recv_vcc = NULL;
1092 * Insert entry to lec_arp_table
1093 * LANE2: Add to the end of the list to satisfy 8.1.13
1095 static __inline__ void
1096 lec_arp_put(struct lec_arp_table **lec_arp_tables,
1097 struct lec_arp_table *to_put)
1099 unsigned short place;
1100 unsigned long flags;
1101 struct lec_arp_table *tmp;
1103 save_flags(flags);
1104 cli();
1106 place = HASH(to_put->mac_addr[ETH_ALEN-1]);
1107 tmp = lec_arp_tables[place];
1108 to_put->next = NULL;
1109 if (tmp == NULL)
1110 lec_arp_tables[place] = to_put;
1112 else { /* add to the end */
1113 while (tmp->next)
1114 tmp = tmp->next;
1115 tmp->next = to_put;
1118 restore_flags(flags);
1119 DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1120 0xff&to_put->mac_addr[0], 0xff&to_put->mac_addr[1],
1121 0xff&to_put->mac_addr[2], 0xff&to_put->mac_addr[3],
1122 0xff&to_put->mac_addr[4], 0xff&to_put->mac_addr[5]);
1126 * Remove entry from lec_arp_table
1128 static __inline__ int
1129 lec_arp_remove(struct lec_arp_table **lec_arp_tables,
1130 struct lec_arp_table *to_remove)
1132 unsigned short place;
1133 struct lec_arp_table *tmp;
1134 unsigned long flags;
1135 int remove_vcc=1;
1137 save_flags(flags);
1138 cli();
1140 if (!to_remove) {
1141 restore_flags(flags);
1142 return -1;
1144 place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
1145 tmp = lec_arp_tables[place];
1146 if (tmp == to_remove) {
1147 lec_arp_tables[place] = tmp->next;
1148 } else {
1149 while(tmp && tmp->next != to_remove) {
1150 tmp = tmp->next;
1152 if (!tmp) {/* Entry was not found */
1153 restore_flags(flags);
1154 return -1;
1157 tmp->next = to_remove->next;
1158 del_timer(&to_remove->timer);
1160 /* If this is the only MAC connected to this VCC, also tear down
1161 the VCC */
1162 if (to_remove->status >= ESI_FLUSH_PENDING) {
1164 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
1166 for(place=0;place<LEC_ARP_TABLE_SIZE;place++) {
1167 for(tmp=lec_arp_tables[place];tmp!=NULL;tmp=tmp->next){
1168 if (memcmp(tmp->atm_addr, to_remove->atm_addr,
1169 ATM_ESA_LEN)==0) {
1170 remove_vcc=0;
1171 break;
1175 if (remove_vcc)
1176 lec_arp_clear_vccs(to_remove);
1178 skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
1179 restore_flags(flags);
1180 DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1181 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
1182 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
1183 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]);
1184 return 0;
1187 #if DEBUG_ARP_TABLE
1188 static char*
1189 get_status_string(unsigned char st)
1191 switch(st) {
1192 case ESI_UNKNOWN:
1193 return "ESI_UNKNOWN";
1194 case ESI_ARP_PENDING:
1195 return "ESI_ARP_PENDING";
1196 case ESI_VC_PENDING:
1197 return "ESI_VC_PENDING";
1198 case ESI_FLUSH_PENDING:
1199 return "ESI_FLUSH_PENDING";
1200 case ESI_FORWARD_DIRECT:
1201 return "ESI_FORWARD_DIRECT";
1202 default:
1203 return "<UNKNOWN>";
1206 #endif
1208 void
1209 dump_arp_table(struct lec_priv *priv)
1211 #if DEBUG_ARP_TABLE
1212 int i,j, offset;
1213 struct lec_arp_table *rulla;
1214 char buf[1024];
1215 struct lec_arp_table **lec_arp_tables =
1216 (struct lec_arp_table **)priv->lec_arp_tables;
1217 struct lec_arp_table *lec_arp_empty_ones =
1218 (struct lec_arp_table *)priv->lec_arp_empty_ones;
1219 struct lec_arp_table *lec_no_forward =
1220 (struct lec_arp_table *)priv->lec_no_forward;
1221 struct lec_arp_table *mcast_fwds = priv->mcast_fwds;
1224 printk("Dump %p:\n",priv);
1225 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1226 rulla = lec_arp_tables[i];
1227 offset = 0;
1228 offset += sprintf(buf,"%d: %p\n",i, rulla);
1229 while (rulla) {
1230 offset += sprintf(buf+offset,"Mac:");
1231 for(j=0;j<ETH_ALEN;j++) {
1232 offset+=sprintf(buf+offset,
1233 "%2.2x ",
1234 rulla->mac_addr[j]&0xff);
1236 offset +=sprintf(buf+offset,"Atm:");
1237 for(j=0;j<ATM_ESA_LEN;j++) {
1238 offset+=sprintf(buf+offset,
1239 "%2.2x ",
1240 rulla->atm_addr[j]&0xff);
1242 offset+=sprintf(buf+offset,
1243 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1244 rulla->vcc?rulla->vcc->vpi:0,
1245 rulla->vcc?rulla->vcc->vci:0,
1246 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1247 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1248 rulla->last_used,
1249 rulla->timestamp, rulla->no_tries);
1250 offset+=sprintf(buf+offset,
1251 "Flags:%x, Packets_flooded:%x, Status: %s ",
1252 rulla->flags, rulla->packets_flooded,
1253 get_status_string(rulla->status));
1254 offset+=sprintf(buf+offset,"->%p\n",rulla->next);
1255 rulla = rulla->next;
1257 printk("%s",buf);
1259 rulla = lec_no_forward;
1260 if (rulla)
1261 printk("No forward\n");
1262 while(rulla) {
1263 offset=0;
1264 offset += sprintf(buf+offset,"Mac:");
1265 for(j=0;j<ETH_ALEN;j++) {
1266 offset+=sprintf(buf+offset,"%2.2x ",
1267 rulla->mac_addr[j]&0xff);
1269 offset +=sprintf(buf+offset,"Atm:");
1270 for(j=0;j<ATM_ESA_LEN;j++) {
1271 offset+=sprintf(buf+offset,"%2.2x ",
1272 rulla->atm_addr[j]&0xff);
1274 offset+=sprintf(buf+offset,
1275 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1276 rulla->vcc?rulla->vcc->vpi:0,
1277 rulla->vcc?rulla->vcc->vci:0,
1278 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1279 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1280 rulla->last_used,
1281 rulla->timestamp, rulla->no_tries);
1282 offset+=sprintf(buf+offset,
1283 "Flags:%x, Packets_flooded:%x, Status: %s ",
1284 rulla->flags, rulla->packets_flooded,
1285 get_status_string(rulla->status));
1286 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1287 rulla = rulla->next;
1288 printk("%s",buf);
1290 rulla = lec_arp_empty_ones;
1291 if (rulla)
1292 printk("Empty ones\n");
1293 while(rulla) {
1294 offset=0;
1295 offset += sprintf(buf+offset,"Mac:");
1296 for(j=0;j<ETH_ALEN;j++) {
1297 offset+=sprintf(buf+offset,"%2.2x ",
1298 rulla->mac_addr[j]&0xff);
1300 offset +=sprintf(buf+offset,"Atm:");
1301 for(j=0;j<ATM_ESA_LEN;j++) {
1302 offset+=sprintf(buf+offset,"%2.2x ",
1303 rulla->atm_addr[j]&0xff);
1305 offset+=sprintf(buf+offset,
1306 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1307 rulla->vcc?rulla->vcc->vpi:0,
1308 rulla->vcc?rulla->vcc->vci:0,
1309 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1310 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1311 rulla->last_used,
1312 rulla->timestamp, rulla->no_tries);
1313 offset+=sprintf(buf+offset,
1314 "Flags:%x, Packets_flooded:%x, Status: %s ",
1315 rulla->flags, rulla->packets_flooded,
1316 get_status_string(rulla->status));
1317 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1318 rulla = rulla->next;
1319 printk("%s",buf);
1322 rulla = mcast_fwds;
1323 if (rulla)
1324 printk("Multicast Forward VCCs\n");
1325 while(rulla) {
1326 offset=0;
1327 offset += sprintf(buf+offset,"Mac:");
1328 for(j=0;j<ETH_ALEN;j++) {
1329 offset+=sprintf(buf+offset,"%2.2x ",
1330 rulla->mac_addr[j]&0xff);
1332 offset +=sprintf(buf+offset,"Atm:");
1333 for(j=0;j<ATM_ESA_LEN;j++) {
1334 offset+=sprintf(buf+offset,"%2.2x ",
1335 rulla->atm_addr[j]&0xff);
1337 offset+=sprintf(buf+offset,
1338 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1339 rulla->vcc?rulla->vcc->vpi:0,
1340 rulla->vcc?rulla->vcc->vci:0,
1341 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1342 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1343 rulla->last_used,
1344 rulla->timestamp, rulla->no_tries);
1345 offset+=sprintf(buf+offset,
1346 "Flags:%x, Packets_flooded:%x, Status: %s ",
1347 rulla->flags, rulla->packets_flooded,
1348 get_status_string(rulla->status));
1349 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1350 rulla = rulla->next;
1351 printk("%s",buf);
1354 #endif
1358 * Destruction of arp-cache
1360 void
1361 lec_arp_destroy(struct lec_priv *priv)
1363 struct lec_arp_table *entry, *next;
1364 unsigned long flags;
1365 int i;
1367 save_flags(flags);
1368 cli();
1370 del_timer(&priv->lec_arp_timer);
1373 * Remove all entries
1375 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1376 for(entry =priv->lec_arp_tables[i];entry != NULL; entry=next) {
1377 next = entry->next;
1378 lec_arp_remove(priv->lec_arp_tables, entry);
1379 kfree(entry);
1382 entry = priv->lec_arp_empty_ones;
1383 while(entry) {
1384 next = entry->next;
1385 del_timer(&entry->timer);
1386 lec_arp_clear_vccs(entry);
1387 kfree(entry);
1388 entry = next;
1390 priv->lec_arp_empty_ones = NULL;
1391 entry = priv->lec_no_forward;
1392 while(entry) {
1393 next = entry->next;
1394 del_timer(&entry->timer);
1395 lec_arp_clear_vccs(entry);
1396 kfree(entry);
1397 entry = next;
1399 priv->lec_no_forward = NULL;
1400 entry = priv->mcast_fwds;
1401 while(entry) {
1402 next = entry->next;
1403 del_timer(&entry->timer);
1404 lec_arp_clear_vccs(entry);
1405 kfree(entry);
1406 entry = next;
1408 priv->mcast_fwds = NULL;
1409 priv->mcast_vcc = NULL;
1410 memset(priv->lec_arp_tables, 0,
1411 sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE);
1412 restore_flags(flags);
1417 * Find entry by mac_address
1419 static __inline__ struct lec_arp_table*
1420 lec_arp_find(struct lec_priv *priv,
1421 unsigned char *mac_addr)
1423 unsigned short place;
1424 struct lec_arp_table *to_return;
1426 DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1427 mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff,
1428 mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
1429 lec_arp_lock(priv);
1430 place = HASH(mac_addr[ETH_ALEN-1]);
1432 to_return = priv->lec_arp_tables[place];
1433 while(to_return) {
1434 if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
1435 lec_arp_unlock(priv);
1436 return to_return;
1438 to_return = to_return->next;
1440 lec_arp_unlock(priv);
1441 return NULL;
1444 static struct lec_arp_table*
1445 make_entry(struct lec_priv *priv, unsigned char *mac_addr)
1447 struct lec_arp_table *to_return;
1449 to_return=(struct lec_arp_table *)kmalloc(sizeof(struct lec_arp_table),
1450 GFP_ATOMIC);
1451 if (!to_return) {
1452 printk("LEC: Arp entry kmalloc failed\n");
1453 return NULL;
1455 memset(to_return,0,sizeof(struct lec_arp_table));
1456 memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
1457 init_timer(&to_return->timer);
1458 to_return->timer.function = lec_arp_expire_arp;
1459 to_return->timer.data = (unsigned long)to_return;
1460 to_return->last_used = jiffies;
1461 to_return->priv = priv;
1462 skb_queue_head_init(&to_return->tx_wait);
1463 return to_return;
1468 * Arp sent timer expired
1471 static void
1472 lec_arp_expire_arp(unsigned long data)
1474 struct lec_arp_table *entry;
1476 entry = (struct lec_arp_table *)data;
1478 del_timer(&entry->timer);
1480 DPRINTK("lec_arp_expire_arp\n");
1481 if (entry->status == ESI_ARP_PENDING) {
1482 if (entry->no_tries <= entry->priv->max_retry_count) {
1483 if (entry->is_rdesc)
1484 send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL);
1485 else
1486 send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
1487 entry->no_tries++;
1489 entry->timer.expires = jiffies + (1*HZ);
1490 add_timer(&entry->timer);
1496 * Unknown/unused vcc expire, remove associated entry
1499 static void
1500 lec_arp_expire_vcc(unsigned long data)
1502 struct lec_arp_table *to_remove = (struct lec_arp_table*)data;
1503 struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
1504 struct lec_arp_table *entry = NULL;
1506 del_timer(&to_remove->timer);
1508 DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
1509 to_remove, priv,
1510 to_remove->vcc?to_remove->recv_vcc->vpi:0,
1511 to_remove->vcc?to_remove->recv_vcc->vci:0);
1512 DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward);
1513 if (to_remove == priv->lec_arp_empty_ones)
1514 priv->lec_arp_empty_ones = to_remove->next;
1515 else {
1516 entry = priv->lec_arp_empty_ones;
1517 while (entry && entry->next != to_remove)
1518 entry = entry->next;
1519 if (entry)
1520 entry->next = to_remove->next;
1522 if (!entry) {
1523 if (to_remove == priv->lec_no_forward) {
1524 priv->lec_no_forward = to_remove->next;
1525 } else {
1526 entry = priv->lec_no_forward;
1527 while (entry && entry->next != to_remove)
1528 entry = entry->next;
1529 if (entry)
1530 entry->next = to_remove->next;
1533 lec_arp_clear_vccs(to_remove);
1534 kfree(to_remove);
1538 * Expire entries.
1539 * 1. Re-set timer
1540 * 2. For each entry, delete entries that have aged past the age limit.
1541 * 3. For each entry, depending on the status of the entry, perform
1542 * the following maintenance.
1543 * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the
1544 * tick_count is above the max_unknown_frame_time, clear
1545 * the tick_count to zero and clear the packets_flooded counter
1546 * to zero. This supports the packet rate limit per address
1547 * while flooding unknowns.
1548 * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater
1549 * than or equal to the path_switching_delay, change the status
1550 * to ESI_FORWARD_DIRECT. This causes the flush period to end
1551 * regardless of the progress of the flush protocol.
1553 static void
1554 lec_arp_check_expire(unsigned long data)
1556 struct lec_priv *priv = (struct lec_priv *)data;
1557 struct lec_arp_table **lec_arp_tables =
1558 (struct lec_arp_table **)priv->lec_arp_tables;
1559 struct lec_arp_table *entry, *next;
1560 unsigned long now;
1561 unsigned long time_to_check;
1562 int i;
1564 del_timer(&priv->lec_arp_timer);
1566 DPRINTK("lec_arp_check_expire %p,%d\n",priv,
1567 priv->lec_arp_lock_var.counter);
1568 DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
1569 priv->lec_no_forward);
1570 if (!priv->lec_arp_lock_var.counter) {
1571 lec_arp_lock(priv);
1572 now = jiffies;
1573 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1574 for(entry = lec_arp_tables[i];entry != NULL;) {
1575 if ((entry->flags) & LEC_REMOTE_FLAG &&
1576 priv->topology_change)
1577 time_to_check=priv->forward_delay_time;
1578 else
1579 time_to_check = priv->aging_time;
1581 DPRINTK("About to expire: %lx - %lx > %lx\n",
1582 now,entry->last_used, time_to_check);
1583 if( time_after(now, entry->last_used+
1584 time_to_check) &&
1585 !(entry->flags & LEC_PERMANENT_FLAG) &&
1586 !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */
1587 /* Remove entry */
1588 DPRINTK("LEC:Entry timed out\n");
1589 next = entry->next;
1590 lec_arp_remove(lec_arp_tables, entry);
1591 kfree(entry);
1592 entry = next;
1593 } else {
1594 /* Something else */
1595 if ((entry->status == ESI_VC_PENDING ||
1596 entry->status == ESI_ARP_PENDING)
1597 && time_after_eq(now,
1598 entry->timestamp +
1599 priv->max_unknown_frame_time)) {
1600 entry->timestamp = jiffies;
1601 entry->packets_flooded = 0;
1602 if (entry->status == ESI_VC_PENDING)
1603 send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL);
1605 if (entry->status == ESI_FLUSH_PENDING
1607 time_after_eq(now, entry->timestamp+
1608 priv->path_switching_delay)) {
1609 entry->last_used = jiffies;
1610 entry->status =
1611 ESI_FORWARD_DIRECT;
1613 entry = entry->next;
1617 lec_arp_unlock(priv);
1619 priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
1620 add_timer(&priv->lec_arp_timer);
1623 * Try to find vcc where mac_address is attached.
1626 struct atm_vcc*
1627 lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
1628 struct lec_arp_table **ret_entry)
1630 struct lec_arp_table *entry;
1632 if (mac_to_find[0]&0x01) {
1633 switch (priv->lane_version) {
1634 case 1:
1635 return priv->mcast_vcc;
1636 break;
1637 case 2: /* LANE2 wants arp for multicast addresses */
1638 if ( memcmp(mac_to_find, bus_mac, ETH_ALEN) == 0)
1639 return priv->mcast_vcc;
1640 break;
1641 default:
1642 break;
1646 entry = lec_arp_find(priv, mac_to_find);
1648 if (entry) {
1649 if (entry->status == ESI_FORWARD_DIRECT) {
1650 /* Connection Ok */
1651 entry->last_used = jiffies;
1652 *ret_entry = entry;
1653 return entry->vcc;
1655 /* Data direct VC not yet set up, check to see if the unknown
1656 frame count is greater than the limit. If the limit has
1657 not been reached, allow the caller to send packet to
1658 BUS. */
1659 if (entry->status != ESI_FLUSH_PENDING &&
1660 entry->packets_flooded<priv->maximum_unknown_frame_count) {
1661 entry->packets_flooded++;
1662 DPRINTK("LEC_ARP: Flooding..\n");
1663 return priv->mcast_vcc;
1665 /* We got here because entry->status == ESI_FLUSH_PENDING
1666 * or BUS flood limit was reached for an entry which is
1667 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
1669 *ret_entry = entry;
1670 DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc);
1671 return NULL;
1672 } else {
1673 /* No matching entry was found */
1674 entry = make_entry(priv, mac_to_find);
1675 DPRINTK("LEC_ARP: Making entry\n");
1676 if (!entry) {
1677 return priv->mcast_vcc;
1679 lec_arp_put(priv->lec_arp_tables, entry);
1680 /* We want arp-request(s) to be sent */
1681 entry->packets_flooded =1;
1682 entry->status = ESI_ARP_PENDING;
1683 entry->no_tries = 1;
1684 entry->last_used = entry->timestamp = jiffies;
1685 entry->is_rdesc = is_rdesc;
1686 if (entry->is_rdesc)
1687 send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL);
1688 else
1689 send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
1690 entry->timer.expires = jiffies + (1*HZ);
1691 entry->timer.function = lec_arp_expire_arp;
1692 add_timer(&entry->timer);
1693 return priv->mcast_vcc;
1698 lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
1699 unsigned long permanent)
1701 struct lec_arp_table *entry, *next;
1702 int i;
1704 lec_arp_lock(priv);
1705 DPRINTK("lec_addr_delete\n");
1706 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1707 for(entry=priv->lec_arp_tables[i];entry != NULL; entry=next) {
1708 next = entry->next;
1709 if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
1710 && (permanent ||
1711 !(entry->flags & LEC_PERMANENT_FLAG))) {
1712 lec_arp_remove(priv->lec_arp_tables, entry);
1713 kfree(entry);
1715 lec_arp_unlock(priv);
1716 return 0;
1719 lec_arp_unlock(priv);
1720 return -1;
1724 * Notifies: Response to arp_request (atm_addr != NULL)
1726 void
1727 lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
1728 unsigned char *atm_addr, unsigned long remoteflag,
1729 unsigned int targetless_le_arp)
1731 struct lec_arp_table *entry, *tmp;
1732 int i;
1734 DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " ");
1735 DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
1736 mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],
1737 mac_addr[4],mac_addr[5]);
1739 entry = lec_arp_find(priv, mac_addr);
1740 if (entry == NULL && targetless_le_arp)
1741 return; /* LANE2: ignore targetless LE_ARPs for which
1742 * we have no entry in the cache. 7.1.30
1744 lec_arp_lock(priv);
1745 if (priv->lec_arp_empty_ones) {
1746 entry = priv->lec_arp_empty_ones;
1747 if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
1748 priv->lec_arp_empty_ones = entry->next;
1749 } else {
1750 while(entry->next && memcmp(entry->next->atm_addr,
1751 atm_addr, ATM_ESA_LEN))
1752 entry = entry->next;
1753 if (entry->next) {
1754 tmp = entry;
1755 entry = entry->next;
1756 tmp->next = entry->next;
1757 } else
1758 entry = NULL;
1761 if (entry) {
1762 del_timer(&entry->timer);
1763 tmp = lec_arp_find(priv, mac_addr);
1764 if (tmp) {
1765 del_timer(&tmp->timer);
1766 tmp->status = ESI_FORWARD_DIRECT;
1767 memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
1768 tmp->vcc = entry->vcc;
1769 tmp->old_push = entry->old_push;
1770 tmp->last_used = jiffies;
1771 del_timer(&entry->timer);
1772 kfree(entry);
1773 entry=tmp;
1774 } else {
1775 entry->status = ESI_FORWARD_DIRECT;
1776 memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
1777 entry->last_used = jiffies;
1778 lec_arp_put(priv->lec_arp_tables, entry);
1780 if (remoteflag)
1781 entry->flags|=LEC_REMOTE_FLAG;
1782 else
1783 entry->flags&=~LEC_REMOTE_FLAG;
1784 lec_arp_unlock(priv);
1785 DPRINTK("After update\n");
1786 dump_arp_table(priv);
1787 return;
1790 entry = lec_arp_find(priv, mac_addr);
1791 if (!entry) {
1792 entry = make_entry(priv, mac_addr);
1793 entry->status = ESI_UNKNOWN;
1794 lec_arp_put(priv->lec_arp_tables, entry);
1795 /* Temporary, changes before end of function */
1797 memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
1798 del_timer(&entry->timer);
1799 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1800 for(tmp=priv->lec_arp_tables[i];tmp;tmp=tmp->next) {
1801 if (entry != tmp &&
1802 !memcmp(tmp->atm_addr, atm_addr,
1803 ATM_ESA_LEN)) {
1804 /* Vcc to this host exists */
1805 if (tmp->status > ESI_VC_PENDING) {
1807 * ESI_FLUSH_PENDING,
1808 * ESI_FORWARD_DIRECT
1810 entry->vcc = tmp->vcc;
1811 entry->old_push=tmp->old_push;
1813 entry->status=tmp->status;
1814 break;
1818 if (remoteflag)
1819 entry->flags|=LEC_REMOTE_FLAG;
1820 else
1821 entry->flags&=~LEC_REMOTE_FLAG;
1822 if (entry->status == ESI_ARP_PENDING ||
1823 entry->status == ESI_UNKNOWN) {
1824 entry->status = ESI_VC_PENDING;
1825 send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
1827 DPRINTK("After update2\n");
1828 dump_arp_table(priv);
1829 lec_arp_unlock(priv);
1833 * Notifies: Vcc setup ready
1835 void
1836 lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
1837 struct atm_vcc *vcc,
1838 void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb))
1840 struct lec_arp_table *entry;
1841 int i, found_entry=0;
1843 lec_arp_lock(priv);
1844 if (ioc_data->receive == 2) {
1845 /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
1847 DPRINTK("LEC_ARP: Attaching mcast forward\n");
1848 #if 0
1849 entry = lec_arp_find(priv, bus_mac);
1850 if (!entry) {
1851 printk("LEC_ARP: Multicast entry not found!\n");
1852 lec_arp_unlock(priv);
1853 return;
1855 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
1856 entry->recv_vcc = vcc;
1857 entry->old_recv_push = old_push;
1858 #endif
1859 entry = make_entry(priv, bus_mac);
1860 if (entry == NULL) {
1861 lec_arp_unlock(priv);
1862 return;
1864 del_timer(&entry->timer);
1865 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
1866 entry->recv_vcc = vcc;
1867 entry->old_recv_push = old_push;
1868 entry->next = priv->mcast_fwds;
1869 priv->mcast_fwds = entry;
1870 lec_arp_unlock(priv);
1871 return;
1872 } else if (ioc_data->receive == 1) {
1873 /* Vcc which we don't want to make default vcc, attach it
1874 anyway. */
1875 DPRINTK("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",
1876 ioc_data->atm_addr[0],ioc_data->atm_addr[1],
1877 ioc_data->atm_addr[2],ioc_data->atm_addr[3],
1878 ioc_data->atm_addr[4],ioc_data->atm_addr[5],
1879 ioc_data->atm_addr[6],ioc_data->atm_addr[7],
1880 ioc_data->atm_addr[8],ioc_data->atm_addr[9],
1881 ioc_data->atm_addr[10],ioc_data->atm_addr[11],
1882 ioc_data->atm_addr[12],ioc_data->atm_addr[13],
1883 ioc_data->atm_addr[14],ioc_data->atm_addr[15],
1884 ioc_data->atm_addr[16],ioc_data->atm_addr[17],
1885 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
1886 entry = make_entry(priv, bus_mac);
1887 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
1888 memset(entry->mac_addr, 0, ETH_ALEN);
1889 entry->recv_vcc = vcc;
1890 entry->old_recv_push = old_push;
1891 entry->status = ESI_UNKNOWN;
1892 entry->timer.expires = jiffies + priv->vcc_timeout_period;
1893 entry->timer.function = lec_arp_expire_vcc;
1894 add_timer(&entry->timer);
1895 entry->next = priv->lec_no_forward;
1896 priv->lec_no_forward = entry;
1897 lec_arp_unlock(priv);
1898 dump_arp_table(priv);
1899 return;
1901 DPRINTK("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",
1902 ioc_data->atm_addr[0],ioc_data->atm_addr[1],
1903 ioc_data->atm_addr[2],ioc_data->atm_addr[3],
1904 ioc_data->atm_addr[4],ioc_data->atm_addr[5],
1905 ioc_data->atm_addr[6],ioc_data->atm_addr[7],
1906 ioc_data->atm_addr[8],ioc_data->atm_addr[9],
1907 ioc_data->atm_addr[10],ioc_data->atm_addr[11],
1908 ioc_data->atm_addr[12],ioc_data->atm_addr[13],
1909 ioc_data->atm_addr[14],ioc_data->atm_addr[15],
1910 ioc_data->atm_addr[16],ioc_data->atm_addr[17],
1911 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
1912 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1913 for (entry = priv->lec_arp_tables[i];entry;entry=entry->next) {
1914 if (memcmp(ioc_data->atm_addr, entry->atm_addr,
1915 ATM_ESA_LEN)==0) {
1916 DPRINTK("LEC_ARP: Attaching data direct\n");
1917 DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n",
1918 entry->vcc?entry->vcc->vci:0,
1919 entry->recv_vcc?entry->recv_vcc->vci:0);
1920 found_entry=1;
1921 del_timer(&entry->timer);
1922 entry->vcc = vcc;
1923 entry->old_push = old_push;
1924 if (entry->status == ESI_VC_PENDING) {
1925 if(priv->maximum_unknown_frame_count
1926 ==0)
1927 entry->status =
1928 ESI_FORWARD_DIRECT;
1929 else {
1930 entry->timestamp = jiffies;
1931 entry->status =
1932 ESI_FLUSH_PENDING;
1933 #if 0
1934 send_to_lecd(priv,l_flush_xmt,
1935 NULL,
1936 entry->atm_addr,
1937 NULL);
1938 #endif
1940 } else {
1941 /* They were forming a connection
1942 to us, and we to them. Our
1943 ATM address is numerically lower
1944 than theirs, so we make connection
1945 we formed into default VCC (8.1.11).
1946 Connection they made gets torn
1947 down. This might confuse some
1948 clients. Can be changed if
1949 someone reports trouble... */
1955 if (found_entry) {
1956 lec_arp_unlock(priv);
1957 DPRINTK("After vcc was added\n");
1958 dump_arp_table(priv);
1959 return;
1961 /* Not found, snatch address from first data packet that arrives from
1962 this vcc */
1963 entry = make_entry(priv, bus_mac);
1964 entry->vcc = vcc;
1965 entry->old_push = old_push;
1966 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
1967 memset(entry->mac_addr, 0, ETH_ALEN);
1968 entry->status = ESI_UNKNOWN;
1969 entry->next = priv->lec_arp_empty_ones;
1970 priv->lec_arp_empty_ones = entry;
1971 entry->timer.expires = jiffies + priv->vcc_timeout_period;
1972 entry->timer.function = lec_arp_expire_vcc;
1973 add_timer(&entry->timer);
1974 lec_arp_unlock(priv);
1975 DPRINTK("After vcc was added\n");
1976 dump_arp_table(priv);
1979 void
1980 lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
1982 struct lec_arp_table *entry;
1983 int i;
1985 DPRINTK("LEC:lec_flush_complete %lx\n",tran_id);
1986 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1987 for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) {
1988 if (entry->flush_tran_id == tran_id &&
1989 entry->status == ESI_FLUSH_PENDING) {
1990 entry->status = ESI_FORWARD_DIRECT;
1991 DPRINTK("LEC_ARP: Flushed\n");
1995 dump_arp_table(priv);
1998 void
1999 lec_set_flush_tran_id(struct lec_priv *priv,
2000 unsigned char *atm_addr, unsigned long tran_id)
2002 struct lec_arp_table *entry;
2003 int i;
2005 for (i=0;i<LEC_ARP_TABLE_SIZE;i++)
2006 for(entry=priv->lec_arp_tables[i];entry;entry=entry->next)
2007 if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
2008 entry->flush_tran_id = tran_id;
2009 DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry);
2013 int
2014 lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
2016 unsigned char mac_addr[] = {
2017 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2018 struct lec_arp_table *to_add;
2020 lec_arp_lock(priv);
2021 to_add = make_entry(priv, mac_addr);
2022 if (!to_add) {
2023 lec_arp_unlock(priv);
2024 return -ENOMEM;
2026 memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
2027 to_add->status = ESI_FORWARD_DIRECT;
2028 to_add->flags |= LEC_PERMANENT_FLAG;
2029 to_add->vcc = vcc;
2030 to_add->old_push = vcc->push;
2031 vcc->push = lec_push;
2032 priv->mcast_vcc = vcc;
2033 lec_arp_put(priv->lec_arp_tables, to_add);
2034 lec_arp_unlock(priv);
2035 return 0;
2038 void
2039 lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
2041 struct lec_arp_table *entry, *next;
2042 int i;
2044 DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
2045 dump_arp_table(priv);
2046 lec_arp_lock(priv);
2047 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
2048 for(entry = priv->lec_arp_tables[i];entry; entry=next) {
2049 next = entry->next;
2050 if (vcc == entry->vcc) {
2051 lec_arp_remove(priv->lec_arp_tables,entry);
2052 kfree(entry);
2053 if (priv->mcast_vcc == vcc) {
2054 priv->mcast_vcc = NULL;
2060 entry = priv->lec_arp_empty_ones;
2061 priv->lec_arp_empty_ones = NULL;
2062 while (entry != NULL) {
2063 next = entry->next;
2064 if (entry->vcc == vcc) { /* leave it out from the list */
2065 lec_arp_clear_vccs(entry);
2066 del_timer(&entry->timer);
2067 kfree(entry);
2069 else { /* put it back to the list */
2070 entry->next = priv->lec_arp_empty_ones;
2071 priv->lec_arp_empty_ones = entry;
2073 entry = next;
2076 entry = priv->lec_no_forward;
2077 priv->lec_no_forward = NULL;
2078 while (entry != NULL) {
2079 next = entry->next;
2080 if (entry->recv_vcc == vcc) {
2081 lec_arp_clear_vccs(entry);
2082 del_timer(&entry->timer);
2083 kfree(entry);
2085 else {
2086 entry->next = priv->lec_no_forward;
2087 priv->lec_no_forward = entry;
2089 entry = next;
2092 entry = priv->mcast_fwds;
2093 priv->mcast_fwds = NULL;
2094 while (entry != NULL) {
2095 next = entry->next;
2096 if (entry->recv_vcc == vcc) {
2097 lec_arp_clear_vccs(entry);
2098 /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
2099 kfree(entry);
2101 else {
2102 entry->next = priv->mcast_fwds;
2103 priv->mcast_fwds = entry;
2105 entry = next;
2108 lec_arp_unlock(priv);
2109 dump_arp_table(priv);
2112 void
2113 lec_arp_check_empties(struct lec_priv *priv,
2114 struct atm_vcc *vcc, struct sk_buff *skb)
2116 struct lec_arp_table *entry, *prev;
2117 struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
2118 unsigned long flags;
2119 unsigned char *src;
2120 #ifdef CONFIG_TR
2121 struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
2123 if (priv->is_trdev) src = tr_hdr->h_source;
2124 else
2125 #endif
2126 src = hdr->h_source;
2128 lec_arp_lock(priv);
2129 entry = priv->lec_arp_empty_ones;
2130 if (vcc == entry->vcc) {
2131 save_flags(flags);
2132 cli();
2133 del_timer(&entry->timer);
2134 memcpy(entry->mac_addr, src, ETH_ALEN);
2135 entry->status = ESI_FORWARD_DIRECT;
2136 entry->last_used = jiffies;
2137 priv->lec_arp_empty_ones = entry->next;
2138 restore_flags(flags);
2139 /* We might have got an entry */
2140 if ((prev=lec_arp_find(priv,src))) {
2141 lec_arp_remove(priv->lec_arp_tables, prev);
2142 kfree(prev);
2144 lec_arp_put(priv->lec_arp_tables, entry);
2145 lec_arp_unlock(priv);
2146 return;
2148 prev = entry;
2149 entry = entry->next;
2150 while (entry && entry->vcc != vcc) {
2151 prev= entry;
2152 entry = entry->next;
2154 if (!entry) {
2155 DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
2156 lec_arp_unlock(priv);
2157 return;
2159 save_flags(flags);
2160 cli();
2161 del_timer(&entry->timer);
2162 memcpy(entry->mac_addr, src, ETH_ALEN);
2163 entry->status = ESI_FORWARD_DIRECT;
2164 entry->last_used = jiffies;
2165 prev->next = entry->next;
2166 restore_flags(flags);
2167 if ((prev = lec_arp_find(priv, src))) {
2168 lec_arp_remove(priv->lec_arp_tables,prev);
2169 kfree(prev);
2171 lec_arp_put(priv->lec_arp_tables,entry);
2172 lec_arp_unlock(priv);