blob: 543960c86fa88327ba478af74abeb73ad0a5727c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * lec.c: Lan Emulation driver
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Chas Williamsd44f7742006-09-29 17:11:14 -07004 * Marko Kiiskila <mkiiskila@yahoo.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 */
6
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include <linux/kernel.h>
8#include <linux/bitops.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -08009#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
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>
23#include <linux/spinlock.h>
24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
26
27/* TokenRing if needed */
28#ifdef CONFIG_TR
29#include <linux/trdevice.h>
30#endif
31
32/* And atm device */
33#include <linux/atmdev.h>
34#include <linux/atmlec.h>
35
36/* Proxy LEC knows about bridging */
37#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
38#include <linux/if_bridge.h>
39#include "../bridge/br_private.h"
40
Chas Williamsd44f7742006-09-29 17:11:14 -070041static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#endif
43
44/* Modular too */
45#include <linux/module.h>
46#include <linux/init.h>
47
48#include "lec.h"
49#include "lec_arpc.h"
50#include "resources.h"
51
52#if 0
53#define DPRINTK printk
54#else
55#define DPRINTK(format,args...)
56#endif
57
Chas Williamsd44f7742006-09-29 17:11:14 -070058#define DUMP_PACKETS 0 /*
59 * 0 = None,
60 * 1 = 30 first bytes
61 * 2 = Whole packet
62 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Chas Williamsd44f7742006-09-29 17:11:14 -070064#define LEC_UNRES_QUE_LEN 8 /*
65 * number of tx packets to queue for a
66 * single destination while waiting for SVC
67 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69static int lec_open(struct net_device *dev);
70static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
71static int lec_close(struct net_device *dev);
72static struct net_device_stats *lec_get_stats(struct net_device *dev);
73static void lec_init(struct net_device *dev);
Chas Williamsd44f7742006-09-29 17:11:14 -070074static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
75 unsigned char *mac_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static int lec_arp_remove(struct lec_priv *priv,
Chas Williamsd44f7742006-09-29 17:11:14 -070077 struct lec_arp_table *to_remove);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078/* LANE2 functions */
Chas Williamsd44f7742006-09-29 17:11:14 -070079static void lane2_associate_ind(struct net_device *dev, u8 *mac_address,
80 u8 *tlvs, u32 sizeoftlvs);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
Chas Williamsd44f7742006-09-29 17:11:14 -070082 u8 **tlvs, u32 *sizeoftlvs);
83static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
84 u8 *tlvs, u32 sizeoftlvs);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
Chas Williamsd44f7742006-09-29 17:11:14 -070086static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 unsigned long permanent);
88static void lec_arp_check_empties(struct lec_priv *priv,
89 struct atm_vcc *vcc, struct sk_buff *skb);
90static void lec_arp_destroy(struct lec_priv *priv);
91static void lec_arp_init(struct lec_priv *priv);
Chas Williamsd44f7742006-09-29 17:11:14 -070092static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 unsigned char *mac_to_find,
94 int is_rdesc,
95 struct lec_arp_table **ret_entry);
96static void lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
97 unsigned char *atm_addr, unsigned long remoteflag,
98 unsigned int targetless_le_arp);
99static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
100static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
101static void lec_set_flush_tran_id(struct lec_priv *priv,
102 unsigned char *atm_addr,
103 unsigned long tran_id);
104static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
105 struct atm_vcc *vcc,
Chas Williamsd44f7742006-09-29 17:11:14 -0700106 void (*old_push) (struct atm_vcc *vcc,
107 struct sk_buff *skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
109
110static struct lane2_ops lane2_ops = {
Chas Williamsd44f7742006-09-29 17:11:14 -0700111 lane2_resolve, /* resolve, spec 3.1.3 */
112 lane2_associate_req, /* associate_req, spec 3.1.4 */
113 NULL /* associate indicator, spec 3.1.5 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114};
115
Chas Williamsd44f7742006-09-29 17:11:14 -0700116static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118/* Device structures */
119static struct net_device *dev_lec[MAX_LEC_ITF];
120
121#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
122static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
123{
Chas Williamsd44f7742006-09-29 17:11:14 -0700124 struct ethhdr *eth;
125 char *buff;
126 struct lec_priv *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Chas Williamsd44f7742006-09-29 17:11:14 -0700128 /*
129 * Check if this is a BPDU. If so, ask zeppelin to send
130 * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
131 * as the Config BPDU has
132 */
133 eth = (struct ethhdr *)skb->data;
134 buff = skb->data + skb->dev->hard_header_len;
135 if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 struct sock *sk;
Chas Williamsd44f7742006-09-29 17:11:14 -0700137 struct sk_buff *skb2;
138 struct atmlec_msg *mesg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Chas Williamsd44f7742006-09-29 17:11:14 -0700140 skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
141 if (skb2 == NULL)
142 return;
143 skb2->len = sizeof(struct atmlec_msg);
144 mesg = (struct atmlec_msg *)skb2->data;
145 mesg->type = l_topology_change;
146 buff += 4;
147 mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
Chas Williamsd44f7742006-09-29 17:11:14 -0700149 priv = (struct lec_priv *)dev->priv;
150 atm_force_charge(priv->lecd, skb2->truesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 sk = sk_atm(priv->lecd);
Chas Williamsd44f7742006-09-29 17:11:14 -0700152 skb_queue_tail(&sk->sk_receive_queue, skb2);
153 sk->sk_data_ready(sk, skb2->len);
154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Chas Williamsd44f7742006-09-29 17:11:14 -0700156 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157}
158#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
159
160/*
161 * Modelled after tr_type_trans
162 * All multicast and ARE or STE frames go to BUS.
163 * Non source routed frames go by destination address.
164 * Last hop source routed frames go by destination address.
165 * Not last hop source routed frames go by _next_ route descriptor.
166 * Returns pointer to destination MAC address or fills in rdesc
167 * and returns NULL.
168 */
169#ifdef CONFIG_TR
170static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
171{
Chas Williamsd44f7742006-09-29 17:11:14 -0700172 struct trh_hdr *trh;
173 int riflen, num_rdsc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
Chas Williamsd44f7742006-09-29 17:11:14 -0700175 trh = (struct trh_hdr *)packet;
176 if (trh->daddr[0] & (uint8_t) 0x80)
177 return bus_mac; /* multicast */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
Chas Williamsd44f7742006-09-29 17:11:14 -0700179 if (trh->saddr[0] & TR_RII) {
180 riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
181 if ((ntohs(trh->rcf) >> 13) != 0)
182 return bus_mac; /* ARE or STE */
183 } else
184 return trh->daddr; /* not source routed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Chas Williamsd44f7742006-09-29 17:11:14 -0700186 if (riflen < 6)
187 return trh->daddr; /* last hop, source routed */
188
189 /* riflen is 6 or more, packet has more than one route descriptor */
190 num_rdsc = (riflen / 2) - 1;
191 memset(rdesc, 0, ETH_ALEN);
192 /* offset 4 comes from LAN destination field in LE control frames */
193 if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT))
194 memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(uint16_t));
195 else {
196 memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
197 rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
198 }
199
200 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201}
202#endif /* CONFIG_TR */
203
204/*
205 * Open/initialize the netdevice. This is called (in the current kernel)
206 * sometime after booting when the 'ifconfig' program is run.
207 *
208 * This routine should set everything up anew at each open, even
209 * registers that "should" only need to be set once at boot, so that
210 * there is non-reboot way to recover if something goes wrong.
211 */
212
Chas Williamsd44f7742006-09-29 17:11:14 -0700213static int lec_open(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
Chas Williamsd44f7742006-09-29 17:11:14 -0700215 struct lec_priv *priv = (struct lec_priv *)dev->priv;
216
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 netif_start_queue(dev);
Chas Williamsd44f7742006-09-29 17:11:14 -0700218 memset(&priv->stats, 0, sizeof(struct net_device_stats));
219
220 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221}
222
223static __inline__ void
224lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
225{
226 ATM_SKB(skb)->vcc = vcc;
227 ATM_SKB(skb)->atm_options = vcc->atm_options;
228
229 atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
230 if (vcc->send(vcc, skb) < 0) {
231 priv->stats.tx_dropped++;
232 return;
233 }
234
235 priv->stats.tx_packets++;
236 priv->stats.tx_bytes += skb->len;
237}
238
Chas Williamsd44f7742006-09-29 17:11:14 -0700239static void lec_tx_timeout(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
241 printk(KERN_INFO "%s: tx timeout\n", dev->name);
242 dev->trans_start = jiffies;
243 netif_wake_queue(dev);
244}
245
Chas Williamsd44f7742006-09-29 17:11:14 -0700246static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
Chas Williamsd44f7742006-09-29 17:11:14 -0700248 struct sk_buff *skb2;
249 struct lec_priv *priv = (struct lec_priv *)dev->priv;
250 struct lecdatahdr_8023 *lec_h;
251 struct atm_vcc *vcc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 struct lec_arp_table *entry;
Chas Williamsd44f7742006-09-29 17:11:14 -0700253 unsigned char *dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 int min_frame_size;
255#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700256 unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700258 int is_rdesc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259#if DUMP_PACKETS > 0
Chas Williamsd44f7742006-09-29 17:11:14 -0700260 char buf[300];
261 int i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262#endif /* DUMP_PACKETS >0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Chas Williamsd44f7742006-09-29 17:11:14 -0700264 DPRINTK("lec_start_xmit called\n");
265 if (!priv->lecd) {
266 printk("%s:No lecd attached\n", dev->name);
267 priv->stats.tx_errors++;
268 netif_stop_queue(dev);
269 return -EUNATCH;
270 }
271
272 DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
273 (long)skb->head, (long)skb->data, (long)skb->tail,
274 (long)skb->end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
Chas Williamsd44f7742006-09-29 17:11:14 -0700276 if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
277 lec_handle_bridge(skb, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278#endif
279
Chas Williamsd44f7742006-09-29 17:11:14 -0700280 /* Make sure we have room for lec_id */
281 if (skb_headroom(skb) < 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Chas Williamsd44f7742006-09-29 17:11:14 -0700283 DPRINTK("lec_start_xmit: reallocating skb\n");
284 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
285 kfree_skb(skb);
286 if (skb2 == NULL)
287 return 0;
288 skb = skb2;
289 }
290 skb_push(skb, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Chas Williamsd44f7742006-09-29 17:11:14 -0700292 /* Put le header to place, works for TokenRing too */
293 lec_h = (struct lecdatahdr_8023 *)skb->data;
294 lec_h->le_header = htons(priv->lecid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
296#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700297 /*
298 * Ugly. Use this to realign Token Ring packets for
299 * e.g. PCA-200E driver.
300 */
301 if (priv->is_trdev) {
302 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
303 kfree_skb(skb);
304 if (skb2 == NULL)
305 return 0;
306 skb = skb2;
307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308#endif
309
310#if DUMP_PACKETS > 0
Chas Williamsd44f7742006-09-29 17:11:14 -0700311 printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
312 skb->len, priv->lecid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313#if DUMP_PACKETS >= 2
Chas Williamsd44f7742006-09-29 17:11:14 -0700314 for (i = 0; i < skb->len && i < 99; i++) {
315 sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317#elif DUMP_PACKETS >= 1
Chas Williamsd44f7742006-09-29 17:11:14 -0700318 for (i = 0; i < skb->len && i < 30; i++) {
319 sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321#endif /* DUMP_PACKETS >= 1 */
Chas Williamsd44f7742006-09-29 17:11:14 -0700322 if (i == skb->len)
323 printk("%s\n", buf);
324 else
325 printk("%s...\n", buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326#endif /* DUMP_PACKETS > 0 */
327
Chas Williamsd44f7742006-09-29 17:11:14 -0700328 /* Minimum ethernet-frame size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700330 if (priv->is_trdev)
331 min_frame_size = LEC_MINIMUM_8025_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 else
333#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700334 min_frame_size = LEC_MINIMUM_8023_SIZE;
335 if (skb->len < min_frame_size) {
336 if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
337 skb2 = skb_copy_expand(skb, 0,
338 min_frame_size - skb->truesize,
339 GFP_ATOMIC);
340 dev_kfree_skb(skb);
341 if (skb2 == NULL) {
342 priv->stats.tx_dropped++;
343 return 0;
344 }
345 skb = skb2;
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 skb_put(skb, min_frame_size - skb->len);
Chas Williamsd44f7742006-09-29 17:11:14 -0700348 }
349
350 /* Send to right vcc */
351 is_rdesc = 0;
352 dst = lec_h->h_dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700354 if (priv->is_trdev) {
355 dst = get_tr_dst(skb->data + 2, rdesc);
356 if (dst == NULL) {
357 dst = rdesc;
358 is_rdesc = 1;
359 }
360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700362 entry = NULL;
363 vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
364 DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
365 vcc, vcc ? vcc->flags : 0, entry);
366 if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) {
367 if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
368 DPRINTK("%s:lec_start_xmit: queuing packet, ",
369 dev->name);
370 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
371 lec_h->h_dest[0], lec_h->h_dest[1],
372 lec_h->h_dest[2], lec_h->h_dest[3],
373 lec_h->h_dest[4], lec_h->h_dest[5]);
374 skb_queue_tail(&entry->tx_wait, skb);
375 } else {
376 DPRINTK
377 ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ",
378 dev->name);
379 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
380 lec_h->h_dest[0], lec_h->h_dest[1],
381 lec_h->h_dest[2], lec_h->h_dest[3],
382 lec_h->h_dest[4], lec_h->h_dest[5]);
383 priv->stats.tx_dropped++;
384 dev_kfree_skb(skb);
385 }
386 return 0;
387 }
388#if DUMP_PACKETS > 0
389 printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390#endif /* DUMP_PACKETS > 0 */
Chas Williamsd44f7742006-09-29 17:11:14 -0700391
392 while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
393 DPRINTK("lec.c: emptying tx queue, ");
394 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
395 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
396 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 lec_send(vcc, skb2, priv);
Chas Williamsd44f7742006-09-29 17:11:14 -0700398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
400 lec_send(vcc, skb, priv);
401
402 if (!atm_may_send(vcc, 0)) {
403 struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
404
405 vpriv->xoff = 1;
406 netif_stop_queue(dev);
407
408 /*
409 * vcc->pop() might have occurred in between, making
410 * the vcc usuable again. Since xmit is serialized,
411 * this is the only situation we have to re-test.
412 */
413
414 if (atm_may_send(vcc, 0))
415 netif_wake_queue(dev);
416 }
417
418 dev->trans_start = jiffies;
Chas Williamsd44f7742006-09-29 17:11:14 -0700419 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420}
421
422/* The inverse routine to net_open(). */
Chas Williamsd44f7742006-09-29 17:11:14 -0700423static int lec_close(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
Chas Williamsd44f7742006-09-29 17:11:14 -0700425 netif_stop_queue(dev);
426 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427}
428
429/*
430 * Get the current statistics.
431 * This may be called with the card open or closed.
432 */
Chas Williamsd44f7742006-09-29 17:11:14 -0700433static struct net_device_stats *lec_get_stats(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
Chas Williamsd44f7742006-09-29 17:11:14 -0700435 return &((struct lec_priv *)dev->priv)->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
Chas Williamsd44f7742006-09-29 17:11:14 -0700438static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 unsigned long flags;
Chas Williamsd44f7742006-09-29 17:11:14 -0700441 struct net_device *dev = (struct net_device *)vcc->proto_data;
442 struct lec_priv *priv = (struct lec_priv *)dev->priv;
443 struct atmlec_msg *mesg;
444 struct lec_arp_table *entry;
445 int i;
446 char *tmp; /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
448 atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
Chas Williamsd44f7742006-09-29 17:11:14 -0700449 mesg = (struct atmlec_msg *)skb->data;
450 tmp = skb->data;
451 tmp += sizeof(struct atmlec_msg);
452 DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
453 switch (mesg->type) {
454 case l_set_mac_addr:
455 for (i = 0; i < 6; i++) {
456 dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
457 }
458 break;
459 case l_del_mac_addr:
460 for (i = 0; i < 6; i++) {
461 dev->dev_addr[i] = 0;
462 }
463 break;
464 case l_addr_delete:
465 lec_addr_delete(priv, mesg->content.normal.atm_addr,
466 mesg->content.normal.flag);
467 break;
468 case l_topology_change:
469 priv->topology_change = mesg->content.normal.flag;
470 break;
471 case l_flush_complete:
472 lec_flush_complete(priv, mesg->content.normal.flag);
473 break;
474 case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 spin_lock_irqsave(&priv->lec_arp_lock, flags);
Chas Williamsd44f7742006-09-29 17:11:14 -0700476 entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
477 lec_arp_remove(priv, entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
479
Chas Williamsd44f7742006-09-29 17:11:14 -0700480 if (mesg->content.normal.no_source_le_narp)
481 break;
482 /* FALL THROUGH */
483 case l_arp_update:
484 lec_arp_update(priv, mesg->content.normal.mac_addr,
485 mesg->content.normal.atm_addr,
486 mesg->content.normal.flag,
487 mesg->content.normal.targetless_le_arp);
488 DPRINTK("lec: in l_arp_update\n");
489 if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */
490 DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n",
491 mesg->sizeoftlvs);
492 lane2_associate_ind(dev, mesg->content.normal.mac_addr,
493 tmp, mesg->sizeoftlvs);
494 }
495 break;
496 case l_config:
497 priv->maximum_unknown_frame_count =
498 mesg->content.config.maximum_unknown_frame_count;
499 priv->max_unknown_frame_time =
500 (mesg->content.config.max_unknown_frame_time * HZ);
501 priv->max_retry_count = mesg->content.config.max_retry_count;
502 priv->aging_time = (mesg->content.config.aging_time * HZ);
503 priv->forward_delay_time =
504 (mesg->content.config.forward_delay_time * HZ);
505 priv->arp_response_time =
506 (mesg->content.config.arp_response_time * HZ);
507 priv->flush_timeout = (mesg->content.config.flush_timeout * HZ);
508 priv->path_switching_delay =
509 (mesg->content.config.path_switching_delay * HZ);
510 priv->lane_version = mesg->content.config.lane_version; /* LANE2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 priv->lane2_ops = NULL;
512 if (priv->lane_version > 1)
513 priv->lane2_ops = &lane2_ops;
514 if (dev->change_mtu(dev, mesg->content.config.mtu))
515 printk("%s: change_mtu to %d failed\n", dev->name,
Chas Williamsd44f7742006-09-29 17:11:14 -0700516 mesg->content.config.mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 priv->is_proxy = mesg->content.config.is_proxy;
Chas Williamsd44f7742006-09-29 17:11:14 -0700518 break;
519 case l_flush_tran_id:
520 lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
521 mesg->content.normal.flag);
522 break;
523 case l_set_lecid:
524 priv->lecid =
525 (unsigned short)(0xffff & mesg->content.normal.flag);
526 break;
527 case l_should_bridge:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
Chas Williamsd44f7742006-09-29 17:11:14 -0700529 {
530 struct net_bridge_fdb_entry *f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
Chas Williamsd44f7742006-09-29 17:11:14 -0700532 DPRINTK
533 ("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
534 dev->name, mesg->content.proxy.mac_addr[0],
535 mesg->content.proxy.mac_addr[1],
536 mesg->content.proxy.mac_addr[2],
537 mesg->content.proxy.mac_addr[3],
538 mesg->content.proxy.mac_addr[4],
539 mesg->content.proxy.mac_addr[5]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Chas Williamsd44f7742006-09-29 17:11:14 -0700541 if (br_fdb_get_hook == NULL || dev->br_port == NULL)
542 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Chas Williamsd44f7742006-09-29 17:11:14 -0700544 f = br_fdb_get_hook(dev->br_port->br,
545 mesg->content.proxy.mac_addr);
546 if (f != NULL && f->dst->dev != dev
547 && f->dst->state == BR_STATE_FORWARDING) {
548 /* hit from bridge table, send LE_ARP_RESPONSE */
549 struct sk_buff *skb2;
550 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Chas Williamsd44f7742006-09-29 17:11:14 -0700552 DPRINTK
553 ("%s: entry found, responding to zeppelin\n",
554 dev->name);
555 skb2 =
556 alloc_skb(sizeof(struct atmlec_msg),
557 GFP_ATOMIC);
558 if (skb2 == NULL) {
559 br_fdb_put_hook(f);
560 break;
561 }
562 skb2->len = sizeof(struct atmlec_msg);
563 memcpy(skb2->data, mesg,
564 sizeof(struct atmlec_msg));
565 atm_force_charge(priv->lecd, skb2->truesize);
566 sk = sk_atm(priv->lecd);
567 skb_queue_tail(&sk->sk_receive_queue, skb2);
568 sk->sk_data_ready(sk, skb2->len);
569 }
570 if (f != NULL)
571 br_fdb_put_hook(f);
572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
Chas Williamsd44f7742006-09-29 17:11:14 -0700574 break;
575 default:
576 printk("%s: Unknown message type %d\n", dev->name, mesg->type);
577 dev_kfree_skb(skb);
578 return -EINVAL;
579 }
580 dev_kfree_skb(skb);
581 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582}
583
Chas Williamsd44f7742006-09-29 17:11:14 -0700584static void lec_atm_close(struct atm_vcc *vcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
Chas Williamsd44f7742006-09-29 17:11:14 -0700586 struct sk_buff *skb;
587 struct net_device *dev = (struct net_device *)vcc->proto_data;
588 struct lec_priv *priv = (struct lec_priv *)dev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Chas Williamsd44f7742006-09-29 17:11:14 -0700590 priv->lecd = NULL;
591 /* Do something needful? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Chas Williamsd44f7742006-09-29 17:11:14 -0700593 netif_stop_queue(dev);
594 lec_arp_destroy(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Chas Williamsd44f7742006-09-29 17:11:14 -0700596 if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 printk("%s lec_atm_close: closing with messages pending\n",
Chas Williamsd44f7742006-09-29 17:11:14 -0700598 dev->name);
599 while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
600 atm_return(vcc, skb->truesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 dev_kfree_skb(skb);
Chas Williamsd44f7742006-09-29 17:11:14 -0700602 }
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 printk("%s: Shut down!\n", dev->name);
Chas Williamsd44f7742006-09-29 17:11:14 -0700605 module_put(THIS_MODULE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606}
607
608static struct atmdev_ops lecdev_ops = {
Chas Williamsd44f7742006-09-29 17:11:14 -0700609 .close = lec_atm_close,
610 .send = lec_atm_send
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611};
612
613static struct atm_dev lecatm_dev = {
Chas Williamsd44f7742006-09-29 17:11:14 -0700614 .ops = &lecdev_ops,
615 .type = "lec",
616 .number = 999, /* dummy device number */
617 .lock = SPIN_LOCK_UNLOCKED
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618};
619
620/*
621 * LANE2: new argument struct sk_buff *data contains
622 * the LE_ARP based TLVs introduced in the LANE2 spec
623 */
Chas Williamsd44f7742006-09-29 17:11:14 -0700624static int
625send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
626 unsigned char *mac_addr, unsigned char *atm_addr,
627 struct sk_buff *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 struct sock *sk;
630 struct sk_buff *skb;
631 struct atmlec_msg *mesg;
632
633 if (!priv || !priv->lecd) {
634 return -1;
635 }
636 skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
637 if (!skb)
638 return -1;
639 skb->len = sizeof(struct atmlec_msg);
640 mesg = (struct atmlec_msg *)skb->data;
Chas Williamsd44f7742006-09-29 17:11:14 -0700641 memset(mesg, 0, sizeof(struct atmlec_msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 mesg->type = type;
Chas Williamsd44f7742006-09-29 17:11:14 -0700643 if (data != NULL)
644 mesg->sizeoftlvs = data->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (mac_addr)
646 memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
Chas Williamsd44f7742006-09-29 17:11:14 -0700647 else
648 mesg->content.normal.targetless_le_arp = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 if (atm_addr)
650 memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
651
Chas Williamsd44f7742006-09-29 17:11:14 -0700652 atm_force_charge(priv->lecd, skb->truesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 sk = sk_atm(priv->lecd);
654 skb_queue_tail(&sk->sk_receive_queue, skb);
Chas Williamsd44f7742006-09-29 17:11:14 -0700655 sk->sk_data_ready(sk, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Chas Williamsd44f7742006-09-29 17:11:14 -0700657 if (data != NULL) {
658 DPRINTK("lec: about to send %d bytes of data\n", data->len);
659 atm_force_charge(priv->lecd, data->truesize);
660 skb_queue_tail(&sk->sk_receive_queue, data);
661 sk->sk_data_ready(sk, skb->len);
662 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Chas Williamsd44f7742006-09-29 17:11:14 -0700664 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
667/* shamelessly stolen from drivers/net/net_init.c */
668static int lec_change_mtu(struct net_device *dev, int new_mtu)
669{
Chas Williamsd44f7742006-09-29 17:11:14 -0700670 if ((new_mtu < 68) || (new_mtu > 18190))
671 return -EINVAL;
672 dev->mtu = new_mtu;
673 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674}
675
676static void lec_set_multicast_list(struct net_device *dev)
677{
Chas Williamsd44f7742006-09-29 17:11:14 -0700678 /*
679 * by default, all multicast frames arrive over the bus.
680 * eventually support selective multicast service
681 */
682 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683}
684
Chas Williamsd44f7742006-09-29 17:11:14 -0700685static void lec_init(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
Chas Williamsd44f7742006-09-29 17:11:14 -0700687 dev->change_mtu = lec_change_mtu;
688 dev->open = lec_open;
689 dev->stop = lec_close;
690 dev->hard_start_xmit = lec_start_xmit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 dev->tx_timeout = lec_tx_timeout;
692
Chas Williamsd44f7742006-09-29 17:11:14 -0700693 dev->get_stats = lec_get_stats;
694 dev->set_multicast_list = lec_set_multicast_list;
695 dev->do_ioctl = NULL;
696 printk("%s: Initialized!\n", dev->name);
697 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
700static unsigned char lec_ctrl_magic[] = {
Chas Williamsd44f7742006-09-29 17:11:14 -0700701 0xff,
702 0x00,
703 0x01,
704 0x01
705};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Scott Talbert4a7097f2005-09-29 17:30:54 -0700707#define LEC_DATA_DIRECT_8023 2
708#define LEC_DATA_DIRECT_8025 3
709
710static int lec_is_data_direct(struct atm_vcc *vcc)
Chas Williamsd44f7742006-09-29 17:11:14 -0700711{
Scott Talbert4a7097f2005-09-29 17:30:54 -0700712 return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
713 (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
Chas Williamsd44f7742006-09-29 17:11:14 -0700714}
Scott Talbert4a7097f2005-09-29 17:30:54 -0700715
Chas Williamsd44f7742006-09-29 17:11:14 -0700716static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
Scott Talbert4a7097f2005-09-29 17:30:54 -0700718 unsigned long flags;
Chas Williamsd44f7742006-09-29 17:11:14 -0700719 struct net_device *dev = (struct net_device *)vcc->proto_data;
720 struct lec_priv *priv = (struct lec_priv *)dev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722#if DUMP_PACKETS >0
Chas Williamsd44f7742006-09-29 17:11:14 -0700723 int i = 0;
724 char buf[300];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Chas Williamsd44f7742006-09-29 17:11:14 -0700726 printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
727 vcc->vpi, vcc->vci);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700729 if (!skb) {
730 DPRINTK("%s: null skb\n", dev->name);
731 lec_vcc_close(priv, vcc);
732 return;
733 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734#if DUMP_PACKETS > 0
Chas Williamsd44f7742006-09-29 17:11:14 -0700735 printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
736 skb->len, priv->lecid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737#if DUMP_PACKETS >= 2
Chas Williamsd44f7742006-09-29 17:11:14 -0700738 for (i = 0; i < skb->len && i < 99; i++) {
739 sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741#elif DUMP_PACKETS >= 1
Chas Williamsd44f7742006-09-29 17:11:14 -0700742 for (i = 0; i < skb->len && i < 30; i++) {
743 sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745#endif /* DUMP_PACKETS >= 1 */
Chas Williamsd44f7742006-09-29 17:11:14 -0700746 if (i == skb->len)
747 printk("%s\n", buf);
748 else
749 printk("%s...\n", buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750#endif /* DUMP_PACKETS > 0 */
Chas Williamsd44f7742006-09-29 17:11:14 -0700751 if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) { /* Control frame, to daemon */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 struct sock *sk = sk_atm(vcc);
753
Chas Williamsd44f7742006-09-29 17:11:14 -0700754 DPRINTK("%s: To daemon\n", dev->name);
755 skb_queue_tail(&sk->sk_receive_queue, skb);
756 sk->sk_data_ready(sk, skb->len);
757 } else { /* Data frame, queue to protocol handlers */
Scott Talbert4a7097f2005-09-29 17:30:54 -0700758 struct lec_arp_table *entry;
Chas Williamsd44f7742006-09-29 17:11:14 -0700759 unsigned char *src, *dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Chas Williamsd44f7742006-09-29 17:11:14 -0700761 atm_return(vcc, skb->truesize);
762 if (*(uint16_t *) skb->data == htons(priv->lecid) ||
763 !priv->lecd || !(dev->flags & IFF_UP)) {
764 /*
765 * Probably looping back, or if lecd is missing,
766 * lecd has gone down
767 */
768 DPRINTK("Ignoring frame...\n");
769 dev_kfree_skb(skb);
770 return;
771 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700773 if (priv->is_trdev)
774 dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
775 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700777 dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
Scott Talbert4a7097f2005-09-29 17:30:54 -0700778
Chas Williamsd44f7742006-09-29 17:11:14 -0700779 /*
780 * If this is a Data Direct VCC, and the VCC does not match
Scott Talbert4a7097f2005-09-29 17:30:54 -0700781 * the LE_ARP cache entry, delete the LE_ARP cache entry.
782 */
783 spin_lock_irqsave(&priv->lec_arp_lock, flags);
784 if (lec_is_data_direct(vcc)) {
785#ifdef CONFIG_TR
786 if (priv->is_trdev)
Chas Williamsd44f7742006-09-29 17:11:14 -0700787 src =
788 ((struct lecdatahdr_8025 *)skb->data)->
789 h_source;
Scott Talbert4a7097f2005-09-29 17:30:54 -0700790 else
791#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700792 src =
793 ((struct lecdatahdr_8023 *)skb->data)->
794 h_source;
Scott Talbert4a7097f2005-09-29 17:30:54 -0700795 entry = lec_arp_find(priv, src);
796 if (entry && entry->vcc != vcc) {
797 lec_arp_remove(priv, entry);
798 kfree(entry);
799 }
800 }
801 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Chas Williamsd44f7742006-09-29 17:11:14 -0700803 if (!(dst[0] & 0x01) && /* Never filter Multi/Broadcast */
804 !priv->is_proxy && /* Proxy wants all the packets */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 memcmp(dst, dev->dev_addr, dev->addr_len)) {
Chas Williamsd44f7742006-09-29 17:11:14 -0700806 dev_kfree_skb(skb);
807 return;
808 }
809 if (priv->lec_arp_empty_ones) {
810 lec_arp_check_empties(priv, vcc, skb);
811 }
812 skb->dev = dev;
813 skb_pull(skb, 2); /* skip lec_id */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700815 if (priv->is_trdev)
816 skb->protocol = tr_type_trans(skb, dev);
817 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700819 skb->protocol = eth_type_trans(skb, dev);
820 priv->stats.rx_packets++;
821 priv->stats.rx_bytes += skb->len;
822 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
823 netif_rx(skb);
824 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825}
826
Chas Williamsd44f7742006-09-29 17:11:14 -0700827static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
829 struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
830 struct net_device *dev = skb->dev;
831
832 if (vpriv == NULL) {
833 printk("lec_pop(): vpriv = NULL!?!?!?\n");
834 return;
835 }
836
837 vpriv->old_pop(vcc, skb);
838
839 if (vpriv->xoff && atm_may_send(vcc, 0)) {
840 vpriv->xoff = 0;
841 if (netif_running(dev) && netif_queue_stopped(dev))
842 netif_wake_queue(dev);
843 }
844}
845
Chas Williamsd44f7742006-09-29 17:11:14 -0700846static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847{
848 struct lec_vcc_priv *vpriv;
Chas Williamsd44f7742006-09-29 17:11:14 -0700849 int bytes_left;
850 struct atmlec_ioc ioc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
Chas Williamsd44f7742006-09-29 17:11:14 -0700852 /* Lecd must be up in this case */
853 bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
854 if (bytes_left != 0) {
855 printk
856 ("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
857 bytes_left);
858 }
859 if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
860 !dev_lec[ioc_data.dev_num])
861 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
863 return -ENOMEM;
864 vpriv->xoff = 0;
865 vpriv->old_pop = vcc->pop;
866 vcc->user_back = vpriv;
867 vcc->pop = lec_pop;
Chas Williamsd44f7742006-09-29 17:11:14 -0700868 lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
869 &ioc_data, vcc, vcc->push);
870 vcc->proto_data = dev_lec[ioc_data.dev_num];
871 vcc->push = lec_push;
872 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873}
874
Chas Williamsd44f7742006-09-29 17:11:14 -0700875static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876{
Chas Williamsd44f7742006-09-29 17:11:14 -0700877 if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
878 return -EINVAL;
879 vcc->proto_data = dev_lec[arg];
880 return (lec_mcast_make((struct lec_priv *)dev_lec[arg]->priv, vcc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881}
882
883/* Initialize device. */
Chas Williamsd44f7742006-09-29 17:11:14 -0700884static int lecd_attach(struct atm_vcc *vcc, int arg)
885{
886 int i;
887 struct lec_priv *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
Chas Williamsd44f7742006-09-29 17:11:14 -0700889 if (arg < 0)
890 i = 0;
891 else
892 i = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700894 if (arg >= MAX_LEC_ITF)
895 return -EINVAL;
896#else /* Reserve the top NUM_TR_DEVS for TR */
897 if (arg >= (MAX_LEC_ITF - NUM_TR_DEVS))
898 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700900 if (!dev_lec[i]) {
901 int is_trdev, size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
Chas Williamsd44f7742006-09-29 17:11:14 -0700903 is_trdev = 0;
904 if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
905 is_trdev = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Chas Williamsd44f7742006-09-29 17:11:14 -0700907 size = sizeof(struct lec_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908#ifdef CONFIG_TR
Chas Williamsd44f7742006-09-29 17:11:14 -0700909 if (is_trdev)
910 dev_lec[i] = alloc_trdev(size);
911 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912#endif
Chas Williamsd44f7742006-09-29 17:11:14 -0700913 dev_lec[i] = alloc_etherdev(size);
914 if (!dev_lec[i])
915 return -ENOMEM;
916 snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
917 if (register_netdev(dev_lec[i])) {
918 free_netdev(dev_lec[i]);
919 return -EINVAL;
920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
Chas Williamsd44f7742006-09-29 17:11:14 -0700922 priv = dev_lec[i]->priv;
923 priv->is_trdev = is_trdev;
924 lec_init(dev_lec[i]);
925 } else {
926 priv = dev_lec[i]->priv;
927 if (priv->lecd)
928 return -EADDRINUSE;
929 }
930 lec_arp_init(priv);
931 priv->itfnum = i; /* LANE2 addition */
932 priv->lecd = vcc;
933 vcc->dev = &lecatm_dev;
934 vcc_insert_socket(sk_atm(vcc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Chas Williamsd44f7742006-09-29 17:11:14 -0700936 vcc->proto_data = dev_lec[i];
937 set_bit(ATM_VF_META, &vcc->flags);
938 set_bit(ATM_VF_READY, &vcc->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Chas Williamsd44f7742006-09-29 17:11:14 -0700940 /* Set default values to these variables */
941 priv->maximum_unknown_frame_count = 1;
942 priv->max_unknown_frame_time = (1 * HZ);
943 priv->vcc_timeout_period = (1200 * HZ);
944 priv->max_retry_count = 1;
945 priv->aging_time = (300 * HZ);
946 priv->forward_delay_time = (15 * HZ);
947 priv->topology_change = 0;
948 priv->arp_response_time = (1 * HZ);
949 priv->flush_timeout = (4 * HZ);
950 priv->path_switching_delay = (6 * HZ);
951
952 if (dev_lec[i]->flags & IFF_UP) {
953 netif_start_queue(dev_lec[i]);
954 }
955 __module_get(THIS_MODULE);
956 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957}
958
959#ifdef CONFIG_PROC_FS
Chas Williamsd44f7742006-09-29 17:11:14 -0700960static char *lec_arp_get_status_string(unsigned char status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
962 static char *lec_arp_status_string[] = {
963 "ESI_UNKNOWN ",
964 "ESI_ARP_PENDING ",
965 "ESI_VC_PENDING ",
966 "<Undefined> ",
967 "ESI_FLUSH_PENDING ",
968 "ESI_FORWARD_DIRECT"
969 };
970
971 if (status > ESI_FORWARD_DIRECT)
972 status = 3; /* ESI_UNDEFINED */
973 return lec_arp_status_string[status];
974}
975
976static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
977{
978 int i;
979
980 for (i = 0; i < ETH_ALEN; i++)
981 seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff);
982 seq_printf(seq, " ");
983 for (i = 0; i < ATM_ESA_LEN; i++)
984 seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff);
985 seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status),
986 entry->flags & 0xffff);
987 if (entry->vcc)
988 seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);
989 else
Chas Williamsd44f7742006-09-29 17:11:14 -0700990 seq_printf(seq, " ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 if (entry->recv_vcc) {
992 seq_printf(seq, " %3d %3d", entry->recv_vcc->vpi,
993 entry->recv_vcc->vci);
Chas Williamsd44f7742006-09-29 17:11:14 -0700994 }
995 seq_putc(seq, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996}
997
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998struct lec_state {
999 unsigned long flags;
1000 struct lec_priv *locked;
1001 struct lec_arp_table *entry;
1002 struct net_device *dev;
1003 int itf;
1004 int arp_table;
1005 int misc_table;
1006};
1007
1008static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl,
1009 loff_t *l)
1010{
1011 struct lec_arp_table *e = state->entry;
1012
1013 if (!e)
1014 e = tbl;
1015 if (e == (void *)1) {
1016 e = tbl;
1017 --*l;
1018 }
1019 for (; e; e = e->next) {
1020 if (--*l < 0)
1021 break;
1022 }
1023 state->entry = e;
1024 return (*l < 0) ? state : NULL;
1025}
1026
1027static void *lec_arp_walk(struct lec_state *state, loff_t *l,
Chas Williamsd44f7742006-09-29 17:11:14 -07001028 struct lec_priv *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029{
1030 void *v = NULL;
1031 int p;
1032
1033 for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
1034 v = lec_tbl_walk(state, priv->lec_arp_tables[p], l);
1035 if (v)
1036 break;
1037 }
1038 state->arp_table = p;
1039 return v;
1040}
1041
1042static void *lec_misc_walk(struct lec_state *state, loff_t *l,
1043 struct lec_priv *priv)
1044{
1045 struct lec_arp_table *lec_misc_tables[] = {
1046 priv->lec_arp_empty_ones,
1047 priv->lec_no_forward,
1048 priv->mcast_fwds
1049 };
1050 void *v = NULL;
1051 int q;
1052
1053 for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) {
1054 v = lec_tbl_walk(state, lec_misc_tables[q], l);
1055 if (v)
1056 break;
1057 }
1058 state->misc_table = q;
1059 return v;
1060}
1061
1062static void *lec_priv_walk(struct lec_state *state, loff_t *l,
1063 struct lec_priv *priv)
1064{
1065 if (!state->locked) {
1066 state->locked = priv;
1067 spin_lock_irqsave(&priv->lec_arp_lock, state->flags);
1068 }
Chas Williamsd44f7742006-09-29 17:11:14 -07001069 if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);
1071 state->locked = NULL;
1072 /* Partial state reset for the next time we get called */
1073 state->arp_table = state->misc_table = 0;
1074 }
1075 return state->locked;
1076}
1077
1078static void *lec_itf_walk(struct lec_state *state, loff_t *l)
1079{
1080 struct net_device *dev;
1081 void *v;
1082
1083 dev = state->dev ? state->dev : dev_lec[state->itf];
1084 v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL;
1085 if (!v && dev) {
1086 dev_put(dev);
1087 /* Partial state reset for the next time we get called */
1088 dev = NULL;
1089 }
1090 state->dev = dev;
1091 return v;
1092}
1093
1094static void *lec_get_idx(struct lec_state *state, loff_t l)
1095{
1096 void *v = NULL;
1097
1098 for (; state->itf < MAX_LEC_ITF; state->itf++) {
1099 v = lec_itf_walk(state, &l);
1100 if (v)
1101 break;
1102 }
Chas Williamsd44f7742006-09-29 17:11:14 -07001103 return v;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
1106static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
1107{
1108 struct lec_state *state = seq->private;
1109
1110 state->itf = 0;
1111 state->dev = NULL;
1112 state->locked = NULL;
1113 state->arp_table = 0;
1114 state->misc_table = 0;
1115 state->entry = (void *)1;
1116
Chas Williamsd44f7742006-09-29 17:11:14 -07001117 return *pos ? lec_get_idx(state, *pos) : (void *)1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118}
1119
1120static void lec_seq_stop(struct seq_file *seq, void *v)
1121{
1122 struct lec_state *state = seq->private;
1123
1124 if (state->dev) {
1125 spin_unlock_irqrestore(&state->locked->lec_arp_lock,
1126 state->flags);
1127 dev_put(state->dev);
1128 }
1129}
1130
1131static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1132{
1133 struct lec_state *state = seq->private;
1134
1135 v = lec_get_idx(state, 1);
1136 *pos += !!PTR_ERR(v);
1137 return v;
1138}
1139
1140static int lec_seq_show(struct seq_file *seq, void *v)
1141{
Chas Williamsd44f7742006-09-29 17:11:14 -07001142 static char lec_banner[] = "Itf MAC ATM destination"
1143 " Status Flags "
1144 "VPI/VCI Recv VPI/VCI\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 if (v == (void *)1)
1147 seq_puts(seq, lec_banner);
1148 else {
1149 struct lec_state *state = seq->private;
Chas Williamsd44f7742006-09-29 17:11:14 -07001150 struct net_device *dev = state->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
1152 seq_printf(seq, "%s ", dev->name);
1153 lec_info(seq, state->entry);
1154 }
1155 return 0;
1156}
1157
1158static struct seq_operations lec_seq_ops = {
Chas Williamsd44f7742006-09-29 17:11:14 -07001159 .start = lec_seq_start,
1160 .next = lec_seq_next,
1161 .stop = lec_seq_stop,
1162 .show = lec_seq_show,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163};
1164
1165static int lec_seq_open(struct inode *inode, struct file *file)
1166{
1167 struct lec_state *state;
1168 struct seq_file *seq;
1169 int rc = -EAGAIN;
1170
1171 state = kmalloc(sizeof(*state), GFP_KERNEL);
1172 if (!state) {
1173 rc = -ENOMEM;
1174 goto out;
1175 }
1176
1177 rc = seq_open(file, &lec_seq_ops);
1178 if (rc)
1179 goto out_kfree;
1180 seq = file->private_data;
1181 seq->private = state;
1182out:
1183 return rc;
1184
1185out_kfree:
1186 kfree(state);
1187 goto out;
1188}
1189
1190static int lec_seq_release(struct inode *inode, struct file *file)
1191{
1192 return seq_release_private(inode, file);
1193}
1194
1195static struct file_operations lec_seq_fops = {
Chas Williamsd44f7742006-09-29 17:11:14 -07001196 .owner = THIS_MODULE,
1197 .open = lec_seq_open,
1198 .read = seq_read,
1199 .llseek = seq_lseek,
1200 .release = lec_seq_release,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201};
1202#endif
1203
1204static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1205{
1206 struct atm_vcc *vcc = ATM_SD(sock);
1207 int err = 0;
Chas Williamsd44f7742006-09-29 17:11:14 -07001208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 switch (cmd) {
Chas Williamsd44f7742006-09-29 17:11:14 -07001210 case ATMLEC_CTRL:
1211 case ATMLEC_MCAST:
1212 case ATMLEC_DATA:
1213 if (!capable(CAP_NET_ADMIN))
1214 return -EPERM;
1215 break;
1216 default:
1217 return -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 }
1219
1220 switch (cmd) {
Chas Williamsd44f7742006-09-29 17:11:14 -07001221 case ATMLEC_CTRL:
1222 err = lecd_attach(vcc, (int)arg);
1223 if (err >= 0)
1224 sock->state = SS_CONNECTED;
1225 break;
1226 case ATMLEC_MCAST:
1227 err = lec_mcast_attach(vcc, (int)arg);
1228 break;
1229 case ATMLEC_DATA:
1230 err = lec_vcc_attach(vcc, (void __user *)arg);
1231 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 }
1233
1234 return err;
1235}
1236
1237static struct atm_ioctl lane_ioctl_ops = {
Chas Williamsd44f7742006-09-29 17:11:14 -07001238 .owner = THIS_MODULE,
1239 .ioctl = lane_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240};
1241
1242static int __init lane_module_init(void)
1243{
1244#ifdef CONFIG_PROC_FS
1245 struct proc_dir_entry *p;
1246
1247 p = create_proc_entry("lec", S_IRUGO, atm_proc_root);
1248 if (p)
1249 p->proc_fops = &lec_seq_fops;
1250#endif
1251
1252 register_atm_ioctl(&lane_ioctl_ops);
Chas Williamsd44f7742006-09-29 17:11:14 -07001253 printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
1254 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255}
1256
1257static void __exit lane_module_cleanup(void)
1258{
Chas Williamsd44f7742006-09-29 17:11:14 -07001259 int i;
1260 struct lec_priv *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 remove_proc_entry("lec", atm_proc_root);
1263
1264 deregister_atm_ioctl(&lane_ioctl_ops);
1265
Chas Williamsd44f7742006-09-29 17:11:14 -07001266 for (i = 0; i < MAX_LEC_ITF; i++) {
1267 if (dev_lec[i] != NULL) {
1268 priv = (struct lec_priv *)dev_lec[i]->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 unregister_netdev(dev_lec[i]);
Chas Williamsd44f7742006-09-29 17:11:14 -07001270 free_netdev(dev_lec[i]);
1271 dev_lec[i] = NULL;
1272 }
1273 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Chas Williamsd44f7742006-09-29 17:11:14 -07001275 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276}
1277
1278module_init(lane_module_init);
1279module_exit(lane_module_cleanup);
1280
1281/*
1282 * LANE2: 3.1.3, LE_RESOLVE.request
1283 * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs.
1284 * If sizeoftlvs == NULL the default TLVs associated with with this
1285 * lec will be used.
1286 * If dst_mac == NULL, targetless LE_ARP will be sent
1287 */
1288static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
Chas Williamsd44f7742006-09-29 17:11:14 -07001289 u8 **tlvs, u32 *sizeoftlvs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290{
1291 unsigned long flags;
Chas Williamsd44f7742006-09-29 17:11:14 -07001292 struct lec_priv *priv = (struct lec_priv *)dev->priv;
1293 struct lec_arp_table *table;
1294 struct sk_buff *skb;
1295 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Chas Williamsd44f7742006-09-29 17:11:14 -07001297 if (force == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 spin_lock_irqsave(&priv->lec_arp_lock, flags);
Chas Williamsd44f7742006-09-29 17:11:14 -07001299 table = lec_arp_find(priv, dst_mac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
Chas Williamsd44f7742006-09-29 17:11:14 -07001301 if (table == NULL)
1302 return -1;
1303
1304 *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC);
1305 if (*tlvs == NULL)
1306 return -1;
1307
1308 memcpy(*tlvs, table->tlvs, table->sizeoftlvs);
1309 *sizeoftlvs = table->sizeoftlvs;
1310
1311 return 0;
1312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
1314 if (sizeoftlvs == NULL)
1315 retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
Chas Williamsd44f7742006-09-29 17:11:14 -07001316
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 else {
1318 skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
1319 if (skb == NULL)
1320 return -1;
1321 skb->len = *sizeoftlvs;
1322 memcpy(skb->data, *tlvs, *sizeoftlvs);
1323 retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
1324 }
Chas Williamsd44f7742006-09-29 17:11:14 -07001325 return retval;
1326}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
1328/*
1329 * LANE2: 3.1.4, LE_ASSOCIATE.request
1330 * Associate the *tlvs with the *lan_dst address.
1331 * Will overwrite any previous association
1332 * Returns 1 for success, 0 for failure (out of memory)
1333 *
1334 */
Chas Williamsd44f7742006-09-29 17:11:14 -07001335static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
1336 u8 *tlvs, u32 sizeoftlvs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Chas Williamsd44f7742006-09-29 17:11:14 -07001338 int retval;
1339 struct sk_buff *skb;
1340 struct lec_priv *priv = (struct lec_priv *)dev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Chas Williamsd44f7742006-09-29 17:11:14 -07001342 if (compare_ether_addr(lan_dst, dev->dev_addr))
1343 return (0); /* not our mac address */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Chas Williamsd44f7742006-09-29 17:11:14 -07001345 kfree(priv->tlvs); /* NULL if there was no previous association */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Chas Williamsd44f7742006-09-29 17:11:14 -07001347 priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
1348 if (priv->tlvs == NULL)
1349 return (0);
1350 priv->sizeoftlvs = sizeoftlvs;
1351 memcpy(priv->tlvs, tlvs, sizeoftlvs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Chas Williamsd44f7742006-09-29 17:11:14 -07001353 skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
1354 if (skb == NULL)
1355 return 0;
1356 skb->len = sizeoftlvs;
1357 memcpy(skb->data, tlvs, sizeoftlvs);
1358 retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
1359 if (retval != 0)
1360 printk("lec.c: lane2_associate_req() failed\n");
1361 /*
1362 * If the previous association has changed we must
1363 * somehow notify other LANE entities about the change
1364 */
1365 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366}
1367
1368/*
1369 * LANE2: 3.1.5, LE_ASSOCIATE.indication
1370 *
1371 */
Chas Williamsd44f7742006-09-29 17:11:14 -07001372static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,
1373 u8 *tlvs, u32 sizeoftlvs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
1375#if 0
Chas Williamsd44f7742006-09-29 17:11:14 -07001376 int i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377#endif
1378 struct lec_priv *priv = (struct lec_priv *)dev->priv;
Chas Williamsd44f7742006-09-29 17:11:14 -07001379#if 0 /*
1380 * Why have the TLVs in LE_ARP entries
1381 * since we do not use them? When you
1382 * uncomment this code, make sure the
1383 * TLVs get freed when entry is killed
1384 */
1385 struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Chas Williamsd44f7742006-09-29 17:11:14 -07001387 if (entry == NULL)
1388 return; /* should not happen */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Chas Williamsd44f7742006-09-29 17:11:14 -07001390 kfree(entry->tlvs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Chas Williamsd44f7742006-09-29 17:11:14 -07001392 entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
1393 if (entry->tlvs == NULL)
1394 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Chas Williamsd44f7742006-09-29 17:11:14 -07001396 entry->sizeoftlvs = sizeoftlvs;
1397 memcpy(entry->tlvs, tlvs, sizeoftlvs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398#endif
1399#if 0
Chas Williamsd44f7742006-09-29 17:11:14 -07001400 printk("lec.c: lane2_associate_ind()\n");
1401 printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
1402 while (i < sizeoftlvs)
1403 printk("%02x ", tlvs[i++]);
1404
1405 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406#endif
1407
Chas Williamsd44f7742006-09-29 17:11:14 -07001408 /* tell MPOA about the TLVs we saw */
1409 if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
1410 priv->lane2_ops->associate_indicator(dev, mac_addr,
1411 tlvs, sizeoftlvs);
1412 }
1413 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414}
1415
1416/*
1417 * Here starts what used to lec_arpc.c
1418 *
1419 * lec_arpc.c was added here when making
1420 * lane client modular. October 1997
1421 *
1422 */
1423
1424#include <linux/types.h>
1425#include <linux/sched.h>
1426#include <linux/timer.h>
1427#include <asm/param.h>
1428#include <asm/atomic.h>
1429#include <linux/inetdevice.h>
1430#include <net/route.h>
1431
1432
1433#if 0
1434#define DPRINTK(format,args...)
1435/*
1436#define DPRINTK printk
1437*/
1438#endif
1439#define DEBUG_ARP_TABLE 0
1440
1441#define LEC_ARP_REFRESH_INTERVAL (3*HZ)
1442
1443static void lec_arp_check_expire(unsigned long data);
1444static void lec_arp_expire_arp(unsigned long data);
1445
1446/*
1447 * Arp table funcs
1448 */
1449
1450#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))
1451
1452/*
1453 * Initialization of arp-cache
1454 */
1455static void
1456lec_arp_init(struct lec_priv *priv)
1457{
1458 unsigned short i;
1459
1460 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1461 priv->lec_arp_tables[i] = NULL;
1462 }
1463 spin_lock_init(&priv->lec_arp_lock);
1464 init_timer(&priv->lec_arp_timer);
1465 priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
1466 priv->lec_arp_timer.data = (unsigned long)priv;
1467 priv->lec_arp_timer.function = lec_arp_check_expire;
1468 add_timer(&priv->lec_arp_timer);
1469}
1470
1471static void
1472lec_arp_clear_vccs(struct lec_arp_table *entry)
1473{
1474 if (entry->vcc) {
1475 struct atm_vcc *vcc = entry->vcc;
1476 struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
1477 struct net_device *dev = (struct net_device*) vcc->proto_data;
1478
1479 vcc->pop = vpriv->old_pop;
1480 if (vpriv->xoff)
1481 netif_wake_queue(dev);
1482 kfree(vpriv);
1483 vcc->user_back = NULL;
1484 vcc->push = entry->old_push;
1485 vcc_release_async(vcc, -EPIPE);
1486 vcc = NULL;
1487 }
1488 if (entry->recv_vcc) {
1489 entry->recv_vcc->push = entry->old_recv_push;
1490 vcc_release_async(entry->recv_vcc, -EPIPE);
1491 entry->recv_vcc = NULL;
1492 }
1493}
1494
1495/*
1496 * Insert entry to lec_arp_table
1497 * LANE2: Add to the end of the list to satisfy 8.1.13
1498 */
1499static inline void
1500lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
1501{
1502 unsigned short place;
1503 struct lec_arp_table *tmp;
1504
1505 place = HASH(to_add->mac_addr[ETH_ALEN-1]);
1506 tmp = priv->lec_arp_tables[place];
1507 to_add->next = NULL;
1508 if (tmp == NULL)
1509 priv->lec_arp_tables[place] = to_add;
1510
1511 else { /* add to the end */
1512 while (tmp->next)
1513 tmp = tmp->next;
1514 tmp->next = to_add;
1515 }
1516
1517 DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1518 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1],
1519 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3],
1520 0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]);
1521}
1522
1523/*
1524 * Remove entry from lec_arp_table
1525 */
1526static int
1527lec_arp_remove(struct lec_priv *priv,
1528 struct lec_arp_table *to_remove)
1529{
1530 unsigned short place;
1531 struct lec_arp_table *tmp;
1532 int remove_vcc=1;
1533
1534 if (!to_remove) {
1535 return -1;
1536 }
1537 place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
1538 tmp = priv->lec_arp_tables[place];
1539 if (tmp == to_remove) {
1540 priv->lec_arp_tables[place] = tmp->next;
1541 } else {
1542 while(tmp && tmp->next != to_remove) {
1543 tmp = tmp->next;
1544 }
1545 if (!tmp) {/* Entry was not found */
1546 return -1;
1547 }
1548 }
1549 tmp->next = to_remove->next;
1550 del_timer(&to_remove->timer);
1551
1552 /* If this is the only MAC connected to this VCC, also tear down
1553 the VCC */
1554 if (to_remove->status >= ESI_FLUSH_PENDING) {
1555 /*
1556 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
1557 */
1558 for(place = 0; place < LEC_ARP_TABLE_SIZE; place++) {
1559 for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) {
1560 if (memcmp(tmp->atm_addr, to_remove->atm_addr,
1561 ATM_ESA_LEN)==0) {
1562 remove_vcc=0;
1563 break;
1564 }
1565 }
1566 }
1567 if (remove_vcc)
1568 lec_arp_clear_vccs(to_remove);
1569 }
1570 skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
1571
1572 DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1573 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
1574 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
1575 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]);
1576 return 0;
1577}
1578
1579#if DEBUG_ARP_TABLE
1580static char*
1581get_status_string(unsigned char st)
1582{
1583 switch(st) {
1584 case ESI_UNKNOWN:
1585 return "ESI_UNKNOWN";
1586 case ESI_ARP_PENDING:
1587 return "ESI_ARP_PENDING";
1588 case ESI_VC_PENDING:
1589 return "ESI_VC_PENDING";
1590 case ESI_FLUSH_PENDING:
1591 return "ESI_FLUSH_PENDING";
1592 case ESI_FORWARD_DIRECT:
1593 return "ESI_FORWARD_DIRECT";
1594 default:
1595 return "<UNKNOWN>";
1596 }
1597}
1598#endif
1599
1600static void
1601dump_arp_table(struct lec_priv *priv)
1602{
1603#if DEBUG_ARP_TABLE
1604 int i,j, offset;
1605 struct lec_arp_table *rulla;
1606 char buf[1024];
1607 struct lec_arp_table **lec_arp_tables =
1608 (struct lec_arp_table **)priv->lec_arp_tables;
1609 struct lec_arp_table *lec_arp_empty_ones =
1610 (struct lec_arp_table *)priv->lec_arp_empty_ones;
1611 struct lec_arp_table *lec_no_forward =
1612 (struct lec_arp_table *)priv->lec_no_forward;
1613 struct lec_arp_table *mcast_fwds = priv->mcast_fwds;
1614
1615
1616 printk("Dump %p:\n",priv);
1617 for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
1618 rulla = lec_arp_tables[i];
1619 offset = 0;
1620 offset += sprintf(buf,"%d: %p\n",i, rulla);
1621 while (rulla) {
1622 offset += sprintf(buf+offset,"Mac:");
1623 for(j=0;j<ETH_ALEN;j++) {
1624 offset+=sprintf(buf+offset,
1625 "%2.2x ",
1626 rulla->mac_addr[j]&0xff);
1627 }
1628 offset +=sprintf(buf+offset,"Atm:");
1629 for(j=0;j<ATM_ESA_LEN;j++) {
1630 offset+=sprintf(buf+offset,
1631 "%2.2x ",
1632 rulla->atm_addr[j]&0xff);
1633 }
1634 offset+=sprintf(buf+offset,
1635 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1636 rulla->vcc?rulla->vcc->vpi:0,
1637 rulla->vcc?rulla->vcc->vci:0,
1638 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1639 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1640 rulla->last_used,
1641 rulla->timestamp, rulla->no_tries);
1642 offset+=sprintf(buf+offset,
1643 "Flags:%x, Packets_flooded:%x, Status: %s ",
1644 rulla->flags, rulla->packets_flooded,
1645 get_status_string(rulla->status));
1646 offset+=sprintf(buf+offset,"->%p\n",rulla->next);
1647 rulla = rulla->next;
1648 }
1649 printk("%s",buf);
1650 }
1651 rulla = lec_no_forward;
1652 if (rulla)
1653 printk("No forward\n");
1654 while(rulla) {
1655 offset=0;
1656 offset += sprintf(buf+offset,"Mac:");
1657 for(j=0;j<ETH_ALEN;j++) {
1658 offset+=sprintf(buf+offset,"%2.2x ",
1659 rulla->mac_addr[j]&0xff);
1660 }
1661 offset +=sprintf(buf+offset,"Atm:");
1662 for(j=0;j<ATM_ESA_LEN;j++) {
1663 offset+=sprintf(buf+offset,"%2.2x ",
1664 rulla->atm_addr[j]&0xff);
1665 }
1666 offset+=sprintf(buf+offset,
1667 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1668 rulla->vcc?rulla->vcc->vpi:0,
1669 rulla->vcc?rulla->vcc->vci:0,
1670 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1671 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1672 rulla->last_used,
1673 rulla->timestamp, rulla->no_tries);
1674 offset+=sprintf(buf+offset,
1675 "Flags:%x, Packets_flooded:%x, Status: %s ",
1676 rulla->flags, rulla->packets_flooded,
1677 get_status_string(rulla->status));
1678 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1679 rulla = rulla->next;
1680 printk("%s",buf);
1681 }
1682 rulla = lec_arp_empty_ones;
1683 if (rulla)
1684 printk("Empty ones\n");
1685 while(rulla) {
1686 offset=0;
1687 offset += sprintf(buf+offset,"Mac:");
1688 for(j=0;j<ETH_ALEN;j++) {
1689 offset+=sprintf(buf+offset,"%2.2x ",
1690 rulla->mac_addr[j]&0xff);
1691 }
1692 offset +=sprintf(buf+offset,"Atm:");
1693 for(j=0;j<ATM_ESA_LEN;j++) {
1694 offset+=sprintf(buf+offset,"%2.2x ",
1695 rulla->atm_addr[j]&0xff);
1696 }
1697 offset+=sprintf(buf+offset,
1698 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1699 rulla->vcc?rulla->vcc->vpi:0,
1700 rulla->vcc?rulla->vcc->vci:0,
1701 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1702 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1703 rulla->last_used,
1704 rulla->timestamp, rulla->no_tries);
1705 offset+=sprintf(buf+offset,
1706 "Flags:%x, Packets_flooded:%x, Status: %s ",
1707 rulla->flags, rulla->packets_flooded,
1708 get_status_string(rulla->status));
1709 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1710 rulla = rulla->next;
1711 printk("%s",buf);
1712 }
1713
1714 rulla = mcast_fwds;
1715 if (rulla)
1716 printk("Multicast Forward VCCs\n");
1717 while(rulla) {
1718 offset=0;
1719 offset += sprintf(buf+offset,"Mac:");
1720 for(j=0;j<ETH_ALEN;j++) {
1721 offset+=sprintf(buf+offset,"%2.2x ",
1722 rulla->mac_addr[j]&0xff);
1723 }
1724 offset +=sprintf(buf+offset,"Atm:");
1725 for(j=0;j<ATM_ESA_LEN;j++) {
1726 offset+=sprintf(buf+offset,"%2.2x ",
1727 rulla->atm_addr[j]&0xff);
1728 }
1729 offset+=sprintf(buf+offset,
1730 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
1731 rulla->vcc?rulla->vcc->vpi:0,
1732 rulla->vcc?rulla->vcc->vci:0,
1733 rulla->recv_vcc?rulla->recv_vcc->vpi:0,
1734 rulla->recv_vcc?rulla->recv_vcc->vci:0,
1735 rulla->last_used,
1736 rulla->timestamp, rulla->no_tries);
1737 offset+=sprintf(buf+offset,
1738 "Flags:%x, Packets_flooded:%x, Status: %s ",
1739 rulla->flags, rulla->packets_flooded,
1740 get_status_string(rulla->status));
1741 offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
1742 rulla = rulla->next;
1743 printk("%s",buf);
1744 }
1745
1746#endif
1747}
1748
1749/*
1750 * Destruction of arp-cache
1751 */
1752static void
1753lec_arp_destroy(struct lec_priv *priv)
1754{
1755 unsigned long flags;
1756 struct lec_arp_table *entry, *next;
1757 int i;
1758
1759 del_timer_sync(&priv->lec_arp_timer);
1760
1761 /*
1762 * Remove all entries
1763 */
1764
1765 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1766 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1767 for(entry = priv->lec_arp_tables[i]; entry != NULL; entry=next) {
1768 next = entry->next;
1769 lec_arp_remove(priv, entry);
1770 kfree(entry);
1771 }
1772 }
1773 entry = priv->lec_arp_empty_ones;
1774 while(entry) {
1775 next = entry->next;
1776 del_timer_sync(&entry->timer);
1777 lec_arp_clear_vccs(entry);
1778 kfree(entry);
1779 entry = next;
1780 }
1781 priv->lec_arp_empty_ones = NULL;
1782 entry = priv->lec_no_forward;
1783 while(entry) {
1784 next = entry->next;
1785 del_timer_sync(&entry->timer);
1786 lec_arp_clear_vccs(entry);
1787 kfree(entry);
1788 entry = next;
1789 }
1790 priv->lec_no_forward = NULL;
1791 entry = priv->mcast_fwds;
1792 while(entry) {
1793 next = entry->next;
1794 /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
1795 lec_arp_clear_vccs(entry);
1796 kfree(entry);
1797 entry = next;
1798 }
1799 priv->mcast_fwds = NULL;
1800 priv->mcast_vcc = NULL;
1801 memset(priv->lec_arp_tables, 0,
1802 sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE);
1803 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1804}
1805
1806
1807/*
1808 * Find entry by mac_address
1809 */
1810static struct lec_arp_table*
1811lec_arp_find(struct lec_priv *priv,
1812 unsigned char *mac_addr)
1813{
1814 unsigned short place;
1815 struct lec_arp_table *to_return;
1816
1817 DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
1818 mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff,
1819 mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
1820 place = HASH(mac_addr[ETH_ALEN-1]);
1821
1822 to_return = priv->lec_arp_tables[place];
1823 while(to_return) {
Kris Katterjohnd3f4a682006-01-09 16:01:43 -08001824 if (!compare_ether_addr(mac_addr, to_return->mac_addr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 return to_return;
1826 }
1827 to_return = to_return->next;
1828 }
1829 return NULL;
1830}
1831
1832static struct lec_arp_table*
1833make_entry(struct lec_priv *priv, unsigned char *mac_addr)
1834{
1835 struct lec_arp_table *to_return;
1836
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07001837 to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 if (!to_return) {
1839 printk("LEC: Arp entry kmalloc failed\n");
1840 return NULL;
1841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
1843 init_timer(&to_return->timer);
1844 to_return->timer.function = lec_arp_expire_arp;
1845 to_return->timer.data = (unsigned long) to_return;
1846 to_return->last_used = jiffies;
1847 to_return->priv = priv;
1848 skb_queue_head_init(&to_return->tx_wait);
1849 return to_return;
1850}
1851
1852/*
1853 *
1854 * Arp sent timer expired
1855 *
1856 */
1857static void
1858lec_arp_expire_arp(unsigned long data)
1859{
1860 struct lec_arp_table *entry;
1861
1862 entry = (struct lec_arp_table *)data;
1863
1864 DPRINTK("lec_arp_expire_arp\n");
1865 if (entry->status == ESI_ARP_PENDING) {
1866 if (entry->no_tries <= entry->priv->max_retry_count) {
1867 if (entry->is_rdesc)
1868 send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL);
1869 else
1870 send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
1871 entry->no_tries++;
1872 }
1873 mod_timer(&entry->timer, jiffies + (1*HZ));
1874 }
1875}
1876
1877/*
1878 *
1879 * Unknown/unused vcc expire, remove associated entry
1880 *
1881 */
1882static void
1883lec_arp_expire_vcc(unsigned long data)
1884{
1885 unsigned long flags;
1886 struct lec_arp_table *to_remove = (struct lec_arp_table*)data;
1887 struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
1888 struct lec_arp_table *entry = NULL;
1889
1890 del_timer(&to_remove->timer);
1891
1892 DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
1893 to_remove, priv,
1894 to_remove->vcc?to_remove->recv_vcc->vpi:0,
1895 to_remove->vcc?to_remove->recv_vcc->vci:0);
1896 DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward);
1897
1898 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1899 if (to_remove == priv->lec_arp_empty_ones)
1900 priv->lec_arp_empty_ones = to_remove->next;
1901 else {
1902 entry = priv->lec_arp_empty_ones;
1903 while (entry && entry->next != to_remove)
1904 entry = entry->next;
1905 if (entry)
1906 entry->next = to_remove->next;
1907 }
1908 if (!entry) {
1909 if (to_remove == priv->lec_no_forward) {
1910 priv->lec_no_forward = to_remove->next;
1911 } else {
1912 entry = priv->lec_no_forward;
1913 while (entry && entry->next != to_remove)
1914 entry = entry->next;
1915 if (entry)
1916 entry->next = to_remove->next;
1917 }
1918 }
1919 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
1920
1921 lec_arp_clear_vccs(to_remove);
1922 kfree(to_remove);
1923}
1924
1925/*
1926 * Expire entries.
1927 * 1. Re-set timer
1928 * 2. For each entry, delete entries that have aged past the age limit.
1929 * 3. For each entry, depending on the status of the entry, perform
1930 * the following maintenance.
1931 * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the
1932 * tick_count is above the max_unknown_frame_time, clear
1933 * the tick_count to zero and clear the packets_flooded counter
1934 * to zero. This supports the packet rate limit per address
1935 * while flooding unknowns.
1936 * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater
1937 * than or equal to the path_switching_delay, change the status
1938 * to ESI_FORWARD_DIRECT. This causes the flush period to end
1939 * regardless of the progress of the flush protocol.
1940 */
1941static void
1942lec_arp_check_expire(unsigned long data)
1943{
1944 unsigned long flags;
1945 struct lec_priv *priv = (struct lec_priv *)data;
1946 struct lec_arp_table *entry, *next;
1947 unsigned long now;
1948 unsigned long time_to_check;
1949 int i;
1950
1951 DPRINTK("lec_arp_check_expire %p\n",priv);
1952 DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
1953 priv->lec_no_forward);
1954 now = jiffies;
1955 spin_lock_irqsave(&priv->lec_arp_lock, flags);
1956 for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
1957 for(entry = priv->lec_arp_tables[i]; entry != NULL; ) {
1958 if ((entry->flags) & LEC_REMOTE_FLAG &&
1959 priv->topology_change)
1960 time_to_check = priv->forward_delay_time;
1961 else
1962 time_to_check = priv->aging_time;
1963
1964 DPRINTK("About to expire: %lx - %lx > %lx\n",
1965 now,entry->last_used, time_to_check);
1966 if( time_after(now, entry->last_used+
1967 time_to_check) &&
1968 !(entry->flags & LEC_PERMANENT_FLAG) &&
1969 !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */
1970 /* Remove entry */
1971 DPRINTK("LEC:Entry timed out\n");
1972 next = entry->next;
1973 lec_arp_remove(priv, entry);
1974 kfree(entry);
1975 entry = next;
1976 } else {
1977 /* Something else */
1978 if ((entry->status == ESI_VC_PENDING ||
1979 entry->status == ESI_ARP_PENDING)
1980 && time_after_eq(now,
1981 entry->timestamp +
1982 priv->max_unknown_frame_time)) {
1983 entry->timestamp = jiffies;
1984 entry->packets_flooded = 0;
1985 if (entry->status == ESI_VC_PENDING)
1986 send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL);
1987 }
1988 if (entry->status == ESI_FLUSH_PENDING
1989 &&
1990 time_after_eq(now, entry->timestamp+
1991 priv->path_switching_delay)) {
1992 struct sk_buff *skb;
1993
1994 while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
1995 lec_send(entry->vcc, skb, entry->priv);
1996 entry->last_used = jiffies;
1997 entry->status =
1998 ESI_FORWARD_DIRECT;
1999 }
2000 entry = entry->next;
2001 }
2002 }
2003 }
2004 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2005
2006 mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
2007}
2008/*
2009 * Try to find vcc where mac_address is attached.
2010 *
2011 */
2012static struct atm_vcc*
2013lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
2014 int is_rdesc, struct lec_arp_table **ret_entry)
2015{
2016 unsigned long flags;
2017 struct lec_arp_table *entry;
2018 struct atm_vcc *found;
2019
2020 if (mac_to_find[0] & 0x01) {
2021 switch (priv->lane_version) {
2022 case 1:
2023 return priv->mcast_vcc;
2024 break;
2025 case 2: /* LANE2 wants arp for multicast addresses */
Kris Katterjohnd3f4a682006-01-09 16:01:43 -08002026 if (!compare_ether_addr(mac_to_find, bus_mac))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 return priv->mcast_vcc;
2028 break;
2029 default:
2030 break;
2031 }
2032 }
2033
2034 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2035 entry = lec_arp_find(priv, mac_to_find);
2036
2037 if (entry) {
2038 if (entry->status == ESI_FORWARD_DIRECT) {
2039 /* Connection Ok */
2040 entry->last_used = jiffies;
2041 *ret_entry = entry;
2042 found = entry->vcc;
2043 goto out;
2044 }
Scott Talbert75b895c2005-09-29 17:31:30 -07002045 /* If the LE_ARP cache entry is still pending, reset count to 0
2046 * so another LE_ARP request can be made for this frame.
2047 */
2048 if (entry->status == ESI_ARP_PENDING) {
2049 entry->no_tries = 0;
2050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 /* Data direct VC not yet set up, check to see if the unknown
2052 frame count is greater than the limit. If the limit has
2053 not been reached, allow the caller to send packet to
2054 BUS. */
2055 if (entry->status != ESI_FLUSH_PENDING &&
2056 entry->packets_flooded<priv->maximum_unknown_frame_count) {
2057 entry->packets_flooded++;
2058 DPRINTK("LEC_ARP: Flooding..\n");
2059 found = priv->mcast_vcc;
2060 goto out;
2061 }
2062 /* We got here because entry->status == ESI_FLUSH_PENDING
2063 * or BUS flood limit was reached for an entry which is
2064 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
2065 */
2066 *ret_entry = entry;
2067 DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc);
2068 found = NULL;
2069 } else {
2070 /* No matching entry was found */
2071 entry = make_entry(priv, mac_to_find);
2072 DPRINTK("LEC_ARP: Making entry\n");
2073 if (!entry) {
2074 found = priv->mcast_vcc;
2075 goto out;
2076 }
2077 lec_arp_add(priv, entry);
2078 /* We want arp-request(s) to be sent */
2079 entry->packets_flooded =1;
2080 entry->status = ESI_ARP_PENDING;
2081 entry->no_tries = 1;
2082 entry->last_used = entry->timestamp = jiffies;
2083 entry->is_rdesc = is_rdesc;
2084 if (entry->is_rdesc)
2085 send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL);
2086 else
2087 send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
2088 entry->timer.expires = jiffies + (1*HZ);
2089 entry->timer.function = lec_arp_expire_arp;
2090 add_timer(&entry->timer);
2091 found = priv->mcast_vcc;
2092 }
2093
2094out:
2095 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2096 return found;
2097}
2098
2099static int
2100lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
2101 unsigned long permanent)
2102{
2103 unsigned long flags;
2104 struct lec_arp_table *entry, *next;
2105 int i;
2106
2107 DPRINTK("lec_addr_delete\n");
2108 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2109 for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2110 for(entry = priv->lec_arp_tables[i]; entry != NULL; entry = next) {
2111 next = entry->next;
2112 if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
2113 && (permanent ||
2114 !(entry->flags & LEC_PERMANENT_FLAG))) {
2115 lec_arp_remove(priv, entry);
2116 kfree(entry);
2117 }
2118 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2119 return 0;
2120 }
2121 }
2122 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2123 return -1;
2124}
2125
2126/*
2127 * Notifies: Response to arp_request (atm_addr != NULL)
2128 */
2129static void
2130lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
2131 unsigned char *atm_addr, unsigned long remoteflag,
2132 unsigned int targetless_le_arp)
2133{
2134 unsigned long flags;
2135 struct lec_arp_table *entry, *tmp;
2136 int i;
2137
2138 DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " ");
2139 DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
2140 mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],
2141 mac_addr[4],mac_addr[5]);
2142
2143 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2144 entry = lec_arp_find(priv, mac_addr);
2145 if (entry == NULL && targetless_le_arp)
2146 goto out; /* LANE2: ignore targetless LE_ARPs for which
2147 * we have no entry in the cache. 7.1.30
2148 */
2149 if (priv->lec_arp_empty_ones) {
2150 entry = priv->lec_arp_empty_ones;
2151 if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
2152 priv->lec_arp_empty_ones = entry->next;
2153 } else {
2154 while(entry->next && memcmp(entry->next->atm_addr,
2155 atm_addr, ATM_ESA_LEN))
2156 entry = entry->next;
2157 if (entry->next) {
2158 tmp = entry;
2159 entry = entry->next;
2160 tmp->next = entry->next;
2161 } else
2162 entry = NULL;
2163
2164 }
2165 if (entry) {
2166 del_timer(&entry->timer);
2167 tmp = lec_arp_find(priv, mac_addr);
2168 if (tmp) {
2169 del_timer(&tmp->timer);
2170 tmp->status = ESI_FORWARD_DIRECT;
2171 memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
2172 tmp->vcc = entry->vcc;
2173 tmp->old_push = entry->old_push;
2174 tmp->last_used = jiffies;
2175 del_timer(&entry->timer);
2176 kfree(entry);
2177 entry=tmp;
2178 } else {
2179 entry->status = ESI_FORWARD_DIRECT;
2180 memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
2181 entry->last_used = jiffies;
2182 lec_arp_add(priv, entry);
2183 }
2184 if (remoteflag)
2185 entry->flags|=LEC_REMOTE_FLAG;
2186 else
2187 entry->flags&=~LEC_REMOTE_FLAG;
2188 DPRINTK("After update\n");
2189 dump_arp_table(priv);
2190 goto out;
2191 }
2192 }
2193 entry = lec_arp_find(priv, mac_addr);
2194 if (!entry) {
2195 entry = make_entry(priv, mac_addr);
2196 if (!entry)
2197 goto out;
2198 entry->status = ESI_UNKNOWN;
2199 lec_arp_add(priv, entry);
2200 /* Temporary, changes before end of function */
2201 }
2202 memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
2203 del_timer(&entry->timer);
2204 for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2205 for(tmp = priv->lec_arp_tables[i]; tmp; tmp=tmp->next) {
2206 if (entry != tmp &&
2207 !memcmp(tmp->atm_addr, atm_addr,
2208 ATM_ESA_LEN)) {
2209 /* Vcc to this host exists */
2210 if (tmp->status > ESI_VC_PENDING) {
2211 /*
2212 * ESI_FLUSH_PENDING,
2213 * ESI_FORWARD_DIRECT
2214 */
2215 entry->vcc = tmp->vcc;
2216 entry->old_push=tmp->old_push;
2217 }
2218 entry->status=tmp->status;
2219 break;
2220 }
2221 }
2222 }
2223 if (remoteflag)
2224 entry->flags|=LEC_REMOTE_FLAG;
2225 else
2226 entry->flags&=~LEC_REMOTE_FLAG;
2227 if (entry->status == ESI_ARP_PENDING ||
2228 entry->status == ESI_UNKNOWN) {
2229 entry->status = ESI_VC_PENDING;
2230 send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
2231 }
2232 DPRINTK("After update2\n");
2233 dump_arp_table(priv);
2234out:
2235 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2236}
2237
2238/*
2239 * Notifies: Vcc setup ready
2240 */
2241static void
2242lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
2243 struct atm_vcc *vcc,
2244 void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb))
2245{
2246 unsigned long flags;
2247 struct lec_arp_table *entry;
2248 int i, found_entry=0;
2249
2250 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2251 if (ioc_data->receive == 2) {
2252 /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
2253
2254 DPRINTK("LEC_ARP: Attaching mcast forward\n");
2255#if 0
2256 entry = lec_arp_find(priv, bus_mac);
2257 if (!entry) {
2258 printk("LEC_ARP: Multicast entry not found!\n");
2259 goto out;
2260 }
2261 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2262 entry->recv_vcc = vcc;
2263 entry->old_recv_push = old_push;
2264#endif
2265 entry = make_entry(priv, bus_mac);
2266 if (entry == NULL)
2267 goto out;
2268 del_timer(&entry->timer);
2269 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2270 entry->recv_vcc = vcc;
2271 entry->old_recv_push = old_push;
2272 entry->next = priv->mcast_fwds;
2273 priv->mcast_fwds = entry;
2274 goto out;
2275 } else if (ioc_data->receive == 1) {
2276 /* Vcc which we don't want to make default vcc, attach it
2277 anyway. */
2278 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",
2279 ioc_data->atm_addr[0],ioc_data->atm_addr[1],
2280 ioc_data->atm_addr[2],ioc_data->atm_addr[3],
2281 ioc_data->atm_addr[4],ioc_data->atm_addr[5],
2282 ioc_data->atm_addr[6],ioc_data->atm_addr[7],
2283 ioc_data->atm_addr[8],ioc_data->atm_addr[9],
2284 ioc_data->atm_addr[10],ioc_data->atm_addr[11],
2285 ioc_data->atm_addr[12],ioc_data->atm_addr[13],
2286 ioc_data->atm_addr[14],ioc_data->atm_addr[15],
2287 ioc_data->atm_addr[16],ioc_data->atm_addr[17],
2288 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
2289 entry = make_entry(priv, bus_mac);
2290 if (entry == NULL)
2291 goto out;
2292 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2293 memset(entry->mac_addr, 0, ETH_ALEN);
2294 entry->recv_vcc = vcc;
2295 entry->old_recv_push = old_push;
2296 entry->status = ESI_UNKNOWN;
2297 entry->timer.expires = jiffies + priv->vcc_timeout_period;
2298 entry->timer.function = lec_arp_expire_vcc;
2299 add_timer(&entry->timer);
2300 entry->next = priv->lec_no_forward;
2301 priv->lec_no_forward = entry;
2302 dump_arp_table(priv);
2303 goto out;
2304 }
2305 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",
2306 ioc_data->atm_addr[0],ioc_data->atm_addr[1],
2307 ioc_data->atm_addr[2],ioc_data->atm_addr[3],
2308 ioc_data->atm_addr[4],ioc_data->atm_addr[5],
2309 ioc_data->atm_addr[6],ioc_data->atm_addr[7],
2310 ioc_data->atm_addr[8],ioc_data->atm_addr[9],
2311 ioc_data->atm_addr[10],ioc_data->atm_addr[11],
2312 ioc_data->atm_addr[12],ioc_data->atm_addr[13],
2313 ioc_data->atm_addr[14],ioc_data->atm_addr[15],
2314 ioc_data->atm_addr[16],ioc_data->atm_addr[17],
2315 ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
2316 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2317 for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
2318 if (memcmp(ioc_data->atm_addr, entry->atm_addr,
2319 ATM_ESA_LEN)==0) {
2320 DPRINTK("LEC_ARP: Attaching data direct\n");
2321 DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n",
2322 entry->vcc?entry->vcc->vci:0,
2323 entry->recv_vcc?entry->recv_vcc->vci:0);
2324 found_entry=1;
2325 del_timer(&entry->timer);
2326 entry->vcc = vcc;
2327 entry->old_push = old_push;
2328 if (entry->status == ESI_VC_PENDING) {
2329 if(priv->maximum_unknown_frame_count
2330 ==0)
2331 entry->status =
2332 ESI_FORWARD_DIRECT;
2333 else {
2334 entry->timestamp = jiffies;
2335 entry->status =
2336 ESI_FLUSH_PENDING;
2337#if 0
2338 send_to_lecd(priv,l_flush_xmt,
2339 NULL,
2340 entry->atm_addr,
2341 NULL);
2342#endif
2343 }
2344 } else {
2345 /* They were forming a connection
2346 to us, and we to them. Our
2347 ATM address is numerically lower
2348 than theirs, so we make connection
2349 we formed into default VCC (8.1.11).
2350 Connection they made gets torn
2351 down. This might confuse some
2352 clients. Can be changed if
2353 someone reports trouble... */
2354 ;
2355 }
2356 }
2357 }
2358 }
2359 if (found_entry) {
2360 DPRINTK("After vcc was added\n");
2361 dump_arp_table(priv);
2362 goto out;
2363 }
2364 /* Not found, snatch address from first data packet that arrives from
2365 this vcc */
2366 entry = make_entry(priv, bus_mac);
2367 if (!entry)
2368 goto out;
2369 entry->vcc = vcc;
2370 entry->old_push = old_push;
2371 memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
2372 memset(entry->mac_addr, 0, ETH_ALEN);
2373 entry->status = ESI_UNKNOWN;
2374 entry->next = priv->lec_arp_empty_ones;
2375 priv->lec_arp_empty_ones = entry;
2376 entry->timer.expires = jiffies + priv->vcc_timeout_period;
2377 entry->timer.function = lec_arp_expire_vcc;
2378 add_timer(&entry->timer);
2379 DPRINTK("After vcc was added\n");
2380 dump_arp_table(priv);
2381out:
2382 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2383}
2384
2385static void
2386lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
2387{
2388 unsigned long flags;
2389 struct lec_arp_table *entry;
2390 int i;
2391
2392 DPRINTK("LEC:lec_flush_complete %lx\n",tran_id);
2393 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2394 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
2395 for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
2396 if (entry->flush_tran_id == tran_id &&
2397 entry->status == ESI_FLUSH_PENDING) {
2398 struct sk_buff *skb;
2399
2400 while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
2401 lec_send(entry->vcc, skb, entry->priv);
2402 entry->status = ESI_FORWARD_DIRECT;
2403 DPRINTK("LEC_ARP: Flushed\n");
2404 }
2405 }
2406 }
2407 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2408 dump_arp_table(priv);
2409}
2410
2411static void
2412lec_set_flush_tran_id(struct lec_priv *priv,
2413 unsigned char *atm_addr, unsigned long tran_id)
2414{
2415 unsigned long flags;
2416 struct lec_arp_table *entry;
2417 int i;
2418
2419 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2420 for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
2421 for(entry = priv->lec_arp_tables[i]; entry; entry=entry->next)
2422 if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
2423 entry->flush_tran_id = tran_id;
2424 DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry);
2425 }
2426 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2427}
2428
2429static int
2430lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
2431{
2432 unsigned long flags;
2433 unsigned char mac_addr[] = {
2434 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2435 struct lec_arp_table *to_add;
2436 struct lec_vcc_priv *vpriv;
2437 int err = 0;
2438
2439 if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
2440 return -ENOMEM;
2441 vpriv->xoff = 0;
2442 vpriv->old_pop = vcc->pop;
2443 vcc->user_back = vpriv;
2444 vcc->pop = lec_pop;
2445 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2446 to_add = make_entry(priv, mac_addr);
2447 if (!to_add) {
2448 vcc->pop = vpriv->old_pop;
2449 kfree(vpriv);
2450 err = -ENOMEM;
2451 goto out;
2452 }
2453 memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
2454 to_add->status = ESI_FORWARD_DIRECT;
2455 to_add->flags |= LEC_PERMANENT_FLAG;
2456 to_add->vcc = vcc;
2457 to_add->old_push = vcc->push;
2458 vcc->push = lec_push;
2459 priv->mcast_vcc = vcc;
2460 lec_arp_add(priv, to_add);
2461out:
2462 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2463 return err;
2464}
2465
2466static void
2467lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
2468{
2469 unsigned long flags;
2470 struct lec_arp_table *entry, *next;
2471 int i;
2472
2473 DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
2474 dump_arp_table(priv);
2475 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2476 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
2477 for(entry = priv->lec_arp_tables[i];entry; entry=next) {
2478 next = entry->next;
2479 if (vcc == entry->vcc) {
2480 lec_arp_remove(priv, entry);
2481 kfree(entry);
2482 if (priv->mcast_vcc == vcc) {
2483 priv->mcast_vcc = NULL;
2484 }
2485 }
2486 }
2487 }
2488
2489 entry = priv->lec_arp_empty_ones;
2490 priv->lec_arp_empty_ones = NULL;
2491 while (entry != NULL) {
2492 next = entry->next;
2493 if (entry->vcc == vcc) { /* leave it out from the list */
2494 lec_arp_clear_vccs(entry);
2495 del_timer(&entry->timer);
2496 kfree(entry);
2497 }
2498 else { /* put it back to the list */
2499 entry->next = priv->lec_arp_empty_ones;
2500 priv->lec_arp_empty_ones = entry;
2501 }
2502 entry = next;
2503 }
2504
2505 entry = priv->lec_no_forward;
2506 priv->lec_no_forward = NULL;
2507 while (entry != NULL) {
2508 next = entry->next;
2509 if (entry->recv_vcc == vcc) {
2510 lec_arp_clear_vccs(entry);
2511 del_timer(&entry->timer);
2512 kfree(entry);
2513 }
2514 else {
2515 entry->next = priv->lec_no_forward;
2516 priv->lec_no_forward = entry;
2517 }
2518 entry = next;
2519 }
2520
2521 entry = priv->mcast_fwds;
2522 priv->mcast_fwds = NULL;
2523 while (entry != NULL) {
2524 next = entry->next;
2525 if (entry->recv_vcc == vcc) {
2526 lec_arp_clear_vccs(entry);
2527 /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
2528 kfree(entry);
2529 }
2530 else {
2531 entry->next = priv->mcast_fwds;
2532 priv->mcast_fwds = entry;
2533 }
2534 entry = next;
2535 }
2536
2537 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2538 dump_arp_table(priv);
2539}
2540
2541static void
2542lec_arp_check_empties(struct lec_priv *priv,
2543 struct atm_vcc *vcc, struct sk_buff *skb)
2544{
2545 unsigned long flags;
2546 struct lec_arp_table *entry, *prev;
2547 struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
2548 unsigned char *src;
2549#ifdef CONFIG_TR
2550 struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
2551
2552 if (priv->is_trdev) src = tr_hdr->h_source;
2553 else
2554#endif
2555 src = hdr->h_source;
2556
2557 spin_lock_irqsave(&priv->lec_arp_lock, flags);
2558 entry = priv->lec_arp_empty_ones;
2559 if (vcc == entry->vcc) {
2560 del_timer(&entry->timer);
2561 memcpy(entry->mac_addr, src, ETH_ALEN);
2562 entry->status = ESI_FORWARD_DIRECT;
2563 entry->last_used = jiffies;
2564 priv->lec_arp_empty_ones = entry->next;
2565 /* We might have got an entry */
2566 if ((prev = lec_arp_find(priv,src))) {
2567 lec_arp_remove(priv, prev);
2568 kfree(prev);
2569 }
2570 lec_arp_add(priv, entry);
2571 goto out;
2572 }
2573 prev = entry;
2574 entry = entry->next;
2575 while (entry && entry->vcc != vcc) {
2576 prev= entry;
2577 entry = entry->next;
2578 }
2579 if (!entry) {
2580 DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
2581 goto out;
2582 }
2583 del_timer(&entry->timer);
2584 memcpy(entry->mac_addr, src, ETH_ALEN);
2585 entry->status = ESI_FORWARD_DIRECT;
2586 entry->last_used = jiffies;
2587 prev->next = entry->next;
2588 if ((prev = lec_arp_find(priv, src))) {
2589 lec_arp_remove(priv, prev);
2590 kfree(prev);
2591 }
2592 lec_arp_add(priv, entry);
2593out:
2594 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
2595}
2596MODULE_LICENSE("GPL");