1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * lec.c: Lan Emulation driver 3*1da177e4SLinus Torvalds * Marko Kiiskila mkiiskila@yahoo.com 4*1da177e4SLinus Torvalds * 5*1da177e4SLinus Torvalds */ 6*1da177e4SLinus Torvalds 7*1da177e4SLinus Torvalds #include <linux/config.h> 8*1da177e4SLinus Torvalds #include <linux/kernel.h> 9*1da177e4SLinus Torvalds #include <linux/bitops.h> 10*1da177e4SLinus Torvalds 11*1da177e4SLinus Torvalds /* We are ethernet device */ 12*1da177e4SLinus Torvalds #include <linux/if_ether.h> 13*1da177e4SLinus Torvalds #include <linux/netdevice.h> 14*1da177e4SLinus Torvalds #include <linux/etherdevice.h> 15*1da177e4SLinus Torvalds #include <net/sock.h> 16*1da177e4SLinus Torvalds #include <linux/skbuff.h> 17*1da177e4SLinus Torvalds #include <linux/ip.h> 18*1da177e4SLinus Torvalds #include <asm/byteorder.h> 19*1da177e4SLinus Torvalds #include <asm/uaccess.h> 20*1da177e4SLinus Torvalds #include <net/arp.h> 21*1da177e4SLinus Torvalds #include <net/dst.h> 22*1da177e4SLinus Torvalds #include <linux/proc_fs.h> 23*1da177e4SLinus Torvalds #include <linux/spinlock.h> 24*1da177e4SLinus Torvalds #include <linux/proc_fs.h> 25*1da177e4SLinus Torvalds #include <linux/seq_file.h> 26*1da177e4SLinus Torvalds 27*1da177e4SLinus Torvalds /* TokenRing if needed */ 28*1da177e4SLinus Torvalds #ifdef CONFIG_TR 29*1da177e4SLinus Torvalds #include <linux/trdevice.h> 30*1da177e4SLinus Torvalds #endif 31*1da177e4SLinus Torvalds 32*1da177e4SLinus Torvalds /* And atm device */ 33*1da177e4SLinus Torvalds #include <linux/atmdev.h> 34*1da177e4SLinus Torvalds #include <linux/atmlec.h> 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds /* Proxy LEC knows about bridging */ 37*1da177e4SLinus Torvalds #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 38*1da177e4SLinus Torvalds #include <linux/if_bridge.h> 39*1da177e4SLinus Torvalds #include "../bridge/br_private.h" 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; 42*1da177e4SLinus Torvalds #endif 43*1da177e4SLinus Torvalds 44*1da177e4SLinus Torvalds /* Modular too */ 45*1da177e4SLinus Torvalds #include <linux/module.h> 46*1da177e4SLinus Torvalds #include <linux/init.h> 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds #include "lec.h" 49*1da177e4SLinus Torvalds #include "lec_arpc.h" 50*1da177e4SLinus Torvalds #include "resources.h" 51*1da177e4SLinus Torvalds 52*1da177e4SLinus Torvalds #if 0 53*1da177e4SLinus Torvalds #define DPRINTK printk 54*1da177e4SLinus Torvalds #else 55*1da177e4SLinus Torvalds #define DPRINTK(format,args...) 56*1da177e4SLinus Torvalds #endif 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds #define DUMP_PACKETS 0 /* 0 = None, 59*1da177e4SLinus Torvalds * 1 = 30 first bytes 60*1da177e4SLinus Torvalds * 2 = Whole packet 61*1da177e4SLinus Torvalds */ 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds #define LEC_UNRES_QUE_LEN 8 /* number of tx packets to queue for a 64*1da177e4SLinus Torvalds single destination while waiting for SVC */ 65*1da177e4SLinus Torvalds 66*1da177e4SLinus Torvalds static int lec_open(struct net_device *dev); 67*1da177e4SLinus Torvalds static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev); 68*1da177e4SLinus Torvalds static int lec_close(struct net_device *dev); 69*1da177e4SLinus Torvalds static struct net_device_stats *lec_get_stats(struct net_device *dev); 70*1da177e4SLinus Torvalds static void lec_init(struct net_device *dev); 71*1da177e4SLinus Torvalds static struct lec_arp_table* lec_arp_find(struct lec_priv *priv, 72*1da177e4SLinus Torvalds unsigned char *mac_addr); 73*1da177e4SLinus Torvalds static int lec_arp_remove(struct lec_priv *priv, 74*1da177e4SLinus Torvalds struct lec_arp_table *to_remove); 75*1da177e4SLinus Torvalds /* LANE2 functions */ 76*1da177e4SLinus Torvalds static void lane2_associate_ind (struct net_device *dev, u8 *mac_address, 77*1da177e4SLinus Torvalds u8 *tlvs, u32 sizeoftlvs); 78*1da177e4SLinus Torvalds static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force, 79*1da177e4SLinus Torvalds u8 **tlvs, u32 *sizeoftlvs); 80*1da177e4SLinus Torvalds static int lane2_associate_req (struct net_device *dev, u8 *lan_dst, 81*1da177e4SLinus Torvalds u8 *tlvs, u32 sizeoftlvs); 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, 84*1da177e4SLinus Torvalds unsigned long permanent); 85*1da177e4SLinus Torvalds static void lec_arp_check_empties(struct lec_priv *priv, 86*1da177e4SLinus Torvalds struct atm_vcc *vcc, struct sk_buff *skb); 87*1da177e4SLinus Torvalds static void lec_arp_destroy(struct lec_priv *priv); 88*1da177e4SLinus Torvalds static void lec_arp_init(struct lec_priv *priv); 89*1da177e4SLinus Torvalds static struct atm_vcc* lec_arp_resolve(struct lec_priv *priv, 90*1da177e4SLinus Torvalds unsigned char *mac_to_find, 91*1da177e4SLinus Torvalds int is_rdesc, 92*1da177e4SLinus Torvalds struct lec_arp_table **ret_entry); 93*1da177e4SLinus Torvalds static void lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, 94*1da177e4SLinus Torvalds unsigned char *atm_addr, unsigned long remoteflag, 95*1da177e4SLinus Torvalds unsigned int targetless_le_arp); 96*1da177e4SLinus Torvalds static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id); 97*1da177e4SLinus Torvalds static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc); 98*1da177e4SLinus Torvalds static void lec_set_flush_tran_id(struct lec_priv *priv, 99*1da177e4SLinus Torvalds unsigned char *atm_addr, 100*1da177e4SLinus Torvalds unsigned long tran_id); 101*1da177e4SLinus Torvalds static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, 102*1da177e4SLinus Torvalds struct atm_vcc *vcc, 103*1da177e4SLinus Torvalds void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)); 104*1da177e4SLinus Torvalds static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); 105*1da177e4SLinus Torvalds 106*1da177e4SLinus Torvalds static struct lane2_ops lane2_ops = { 107*1da177e4SLinus Torvalds lane2_resolve, /* resolve, spec 3.1.3 */ 108*1da177e4SLinus Torvalds lane2_associate_req, /* associate_req, spec 3.1.4 */ 109*1da177e4SLinus Torvalds NULL /* associate indicator, spec 3.1.5 */ 110*1da177e4SLinus Torvalds }; 111*1da177e4SLinus Torvalds 112*1da177e4SLinus Torvalds static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; 113*1da177e4SLinus Torvalds 114*1da177e4SLinus Torvalds /* Device structures */ 115*1da177e4SLinus Torvalds static struct net_device *dev_lec[MAX_LEC_ITF]; 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 118*1da177e4SLinus Torvalds static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) 119*1da177e4SLinus Torvalds { 120*1da177e4SLinus Torvalds struct ethhdr *eth; 121*1da177e4SLinus Torvalds char *buff; 122*1da177e4SLinus Torvalds struct lec_priv *priv; 123*1da177e4SLinus Torvalds 124*1da177e4SLinus Torvalds /* Check if this is a BPDU. If so, ask zeppelin to send 125*1da177e4SLinus Torvalds * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit 126*1da177e4SLinus Torvalds * as the Config BPDU has */ 127*1da177e4SLinus Torvalds eth = (struct ethhdr *)skb->data; 128*1da177e4SLinus Torvalds buff = skb->data + skb->dev->hard_header_len; 129*1da177e4SLinus Torvalds if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { 130*1da177e4SLinus Torvalds struct sock *sk; 131*1da177e4SLinus Torvalds struct sk_buff *skb2; 132*1da177e4SLinus Torvalds struct atmlec_msg *mesg; 133*1da177e4SLinus Torvalds 134*1da177e4SLinus Torvalds skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); 135*1da177e4SLinus Torvalds if (skb2 == NULL) return; 136*1da177e4SLinus Torvalds skb2->len = sizeof(struct atmlec_msg); 137*1da177e4SLinus Torvalds mesg = (struct atmlec_msg *)skb2->data; 138*1da177e4SLinus Torvalds mesg->type = l_topology_change; 139*1da177e4SLinus Torvalds buff += 4; 140*1da177e4SLinus Torvalds mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */ 141*1da177e4SLinus Torvalds 142*1da177e4SLinus Torvalds priv = (struct lec_priv *)dev->priv; 143*1da177e4SLinus Torvalds atm_force_charge(priv->lecd, skb2->truesize); 144*1da177e4SLinus Torvalds sk = sk_atm(priv->lecd); 145*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, skb2); 146*1da177e4SLinus Torvalds sk->sk_data_ready(sk, skb2->len); 147*1da177e4SLinus Torvalds } 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds return; 150*1da177e4SLinus Torvalds } 151*1da177e4SLinus Torvalds #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ 152*1da177e4SLinus Torvalds 153*1da177e4SLinus Torvalds /* 154*1da177e4SLinus Torvalds * Modelled after tr_type_trans 155*1da177e4SLinus Torvalds * All multicast and ARE or STE frames go to BUS. 156*1da177e4SLinus Torvalds * Non source routed frames go by destination address. 157*1da177e4SLinus Torvalds * Last hop source routed frames go by destination address. 158*1da177e4SLinus Torvalds * Not last hop source routed frames go by _next_ route descriptor. 159*1da177e4SLinus Torvalds * Returns pointer to destination MAC address or fills in rdesc 160*1da177e4SLinus Torvalds * and returns NULL. 161*1da177e4SLinus Torvalds */ 162*1da177e4SLinus Torvalds #ifdef CONFIG_TR 163*1da177e4SLinus Torvalds static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) 164*1da177e4SLinus Torvalds { 165*1da177e4SLinus Torvalds struct trh_hdr *trh; 166*1da177e4SLinus Torvalds int riflen, num_rdsc; 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds trh = (struct trh_hdr *)packet; 169*1da177e4SLinus Torvalds if (trh->daddr[0] & (uint8_t)0x80) 170*1da177e4SLinus Torvalds return bus_mac; /* multicast */ 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds if (trh->saddr[0] & TR_RII) { 173*1da177e4SLinus Torvalds riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; 174*1da177e4SLinus Torvalds if ((ntohs(trh->rcf) >> 13) != 0) 175*1da177e4SLinus Torvalds return bus_mac; /* ARE or STE */ 176*1da177e4SLinus Torvalds } 177*1da177e4SLinus Torvalds else 178*1da177e4SLinus Torvalds return trh->daddr; /* not source routed */ 179*1da177e4SLinus Torvalds 180*1da177e4SLinus Torvalds if (riflen < 6) 181*1da177e4SLinus Torvalds return trh->daddr; /* last hop, source routed */ 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds /* riflen is 6 or more, packet has more than one route descriptor */ 184*1da177e4SLinus Torvalds num_rdsc = (riflen/2) - 1; 185*1da177e4SLinus Torvalds memset(rdesc, 0, ETH_ALEN); 186*1da177e4SLinus Torvalds /* offset 4 comes from LAN destination field in LE control frames */ 187*1da177e4SLinus Torvalds if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT)) 188*1da177e4SLinus Torvalds memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t)); 189*1da177e4SLinus Torvalds else { 190*1da177e4SLinus Torvalds memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t)); 191*1da177e4SLinus Torvalds rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0)); 192*1da177e4SLinus Torvalds } 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds return NULL; 195*1da177e4SLinus Torvalds } 196*1da177e4SLinus Torvalds #endif /* CONFIG_TR */ 197*1da177e4SLinus Torvalds 198*1da177e4SLinus Torvalds /* 199*1da177e4SLinus Torvalds * Open/initialize the netdevice. This is called (in the current kernel) 200*1da177e4SLinus Torvalds * sometime after booting when the 'ifconfig' program is run. 201*1da177e4SLinus Torvalds * 202*1da177e4SLinus Torvalds * This routine should set everything up anew at each open, even 203*1da177e4SLinus Torvalds * registers that "should" only need to be set once at boot, so that 204*1da177e4SLinus Torvalds * there is non-reboot way to recover if something goes wrong. 205*1da177e4SLinus Torvalds */ 206*1da177e4SLinus Torvalds 207*1da177e4SLinus Torvalds static int 208*1da177e4SLinus Torvalds lec_open(struct net_device *dev) 209*1da177e4SLinus Torvalds { 210*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)dev->priv; 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds netif_start_queue(dev); 213*1da177e4SLinus Torvalds memset(&priv->stats,0,sizeof(struct net_device_stats)); 214*1da177e4SLinus Torvalds 215*1da177e4SLinus Torvalds return 0; 216*1da177e4SLinus Torvalds } 217*1da177e4SLinus Torvalds 218*1da177e4SLinus Torvalds static __inline__ void 219*1da177e4SLinus Torvalds lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv) 220*1da177e4SLinus Torvalds { 221*1da177e4SLinus Torvalds ATM_SKB(skb)->vcc = vcc; 222*1da177e4SLinus Torvalds ATM_SKB(skb)->atm_options = vcc->atm_options; 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); 225*1da177e4SLinus Torvalds if (vcc->send(vcc, skb) < 0) { 226*1da177e4SLinus Torvalds priv->stats.tx_dropped++; 227*1da177e4SLinus Torvalds return; 228*1da177e4SLinus Torvalds } 229*1da177e4SLinus Torvalds 230*1da177e4SLinus Torvalds priv->stats.tx_packets++; 231*1da177e4SLinus Torvalds priv->stats.tx_bytes += skb->len; 232*1da177e4SLinus Torvalds } 233*1da177e4SLinus Torvalds 234*1da177e4SLinus Torvalds static void 235*1da177e4SLinus Torvalds lec_tx_timeout(struct net_device *dev) 236*1da177e4SLinus Torvalds { 237*1da177e4SLinus Torvalds printk(KERN_INFO "%s: tx timeout\n", dev->name); 238*1da177e4SLinus Torvalds dev->trans_start = jiffies; 239*1da177e4SLinus Torvalds netif_wake_queue(dev); 240*1da177e4SLinus Torvalds } 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds static int 243*1da177e4SLinus Torvalds lec_start_xmit(struct sk_buff *skb, struct net_device *dev) 244*1da177e4SLinus Torvalds { 245*1da177e4SLinus Torvalds struct sk_buff *skb2; 246*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)dev->priv; 247*1da177e4SLinus Torvalds struct lecdatahdr_8023 *lec_h; 248*1da177e4SLinus Torvalds struct atm_vcc *vcc; 249*1da177e4SLinus Torvalds struct lec_arp_table *entry; 250*1da177e4SLinus Torvalds unsigned char *dst; 251*1da177e4SLinus Torvalds int min_frame_size; 252*1da177e4SLinus Torvalds #ifdef CONFIG_TR 253*1da177e4SLinus Torvalds unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */ 254*1da177e4SLinus Torvalds #endif 255*1da177e4SLinus Torvalds int is_rdesc; 256*1da177e4SLinus Torvalds #if DUMP_PACKETS > 0 257*1da177e4SLinus Torvalds char buf[300]; 258*1da177e4SLinus Torvalds int i=0; 259*1da177e4SLinus Torvalds #endif /* DUMP_PACKETS >0 */ 260*1da177e4SLinus Torvalds 261*1da177e4SLinus Torvalds DPRINTK("lec_start_xmit called\n"); 262*1da177e4SLinus Torvalds if (!priv->lecd) { 263*1da177e4SLinus Torvalds printk("%s:No lecd attached\n",dev->name); 264*1da177e4SLinus Torvalds priv->stats.tx_errors++; 265*1da177e4SLinus Torvalds netif_stop_queue(dev); 266*1da177e4SLinus Torvalds return -EUNATCH; 267*1da177e4SLinus Torvalds } 268*1da177e4SLinus Torvalds 269*1da177e4SLinus Torvalds DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", 270*1da177e4SLinus Torvalds (long)skb->head, (long)skb->data, (long)skb->tail, 271*1da177e4SLinus Torvalds (long)skb->end); 272*1da177e4SLinus Torvalds #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 273*1da177e4SLinus Torvalds if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0) 274*1da177e4SLinus Torvalds lec_handle_bridge(skb, dev); 275*1da177e4SLinus Torvalds #endif 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds /* Make sure we have room for lec_id */ 278*1da177e4SLinus Torvalds if (skb_headroom(skb) < 2) { 279*1da177e4SLinus Torvalds 280*1da177e4SLinus Torvalds DPRINTK("lec_start_xmit: reallocating skb\n"); 281*1da177e4SLinus Torvalds skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); 282*1da177e4SLinus Torvalds kfree_skb(skb); 283*1da177e4SLinus Torvalds if (skb2 == NULL) return 0; 284*1da177e4SLinus Torvalds skb = skb2; 285*1da177e4SLinus Torvalds } 286*1da177e4SLinus Torvalds skb_push(skb, 2); 287*1da177e4SLinus Torvalds 288*1da177e4SLinus Torvalds /* Put le header to place, works for TokenRing too */ 289*1da177e4SLinus Torvalds lec_h = (struct lecdatahdr_8023*)skb->data; 290*1da177e4SLinus Torvalds lec_h->le_header = htons(priv->lecid); 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds #ifdef CONFIG_TR 293*1da177e4SLinus Torvalds /* Ugly. Use this to realign Token Ring packets for 294*1da177e4SLinus Torvalds * e.g. PCA-200E driver. */ 295*1da177e4SLinus Torvalds if (priv->is_trdev) { 296*1da177e4SLinus Torvalds skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); 297*1da177e4SLinus Torvalds kfree_skb(skb); 298*1da177e4SLinus Torvalds if (skb2 == NULL) return 0; 299*1da177e4SLinus Torvalds skb = skb2; 300*1da177e4SLinus Torvalds } 301*1da177e4SLinus Torvalds #endif 302*1da177e4SLinus Torvalds 303*1da177e4SLinus Torvalds #if DUMP_PACKETS > 0 304*1da177e4SLinus Torvalds printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, 305*1da177e4SLinus Torvalds skb->len, priv->lecid); 306*1da177e4SLinus Torvalds #if DUMP_PACKETS >= 2 307*1da177e4SLinus Torvalds for(i=0;i<skb->len && i <99;i++) { 308*1da177e4SLinus Torvalds sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); 309*1da177e4SLinus Torvalds } 310*1da177e4SLinus Torvalds #elif DUMP_PACKETS >= 1 311*1da177e4SLinus Torvalds for(i=0;i<skb->len && i < 30;i++) { 312*1da177e4SLinus Torvalds sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); 313*1da177e4SLinus Torvalds } 314*1da177e4SLinus Torvalds #endif /* DUMP_PACKETS >= 1 */ 315*1da177e4SLinus Torvalds if (i==skb->len) 316*1da177e4SLinus Torvalds printk("%s\n",buf); 317*1da177e4SLinus Torvalds else 318*1da177e4SLinus Torvalds printk("%s...\n",buf); 319*1da177e4SLinus Torvalds #endif /* DUMP_PACKETS > 0 */ 320*1da177e4SLinus Torvalds 321*1da177e4SLinus Torvalds /* Minimum ethernet-frame size */ 322*1da177e4SLinus Torvalds #ifdef CONFIG_TR 323*1da177e4SLinus Torvalds if (priv->is_trdev) 324*1da177e4SLinus Torvalds min_frame_size = LEC_MINIMUM_8025_SIZE; 325*1da177e4SLinus Torvalds else 326*1da177e4SLinus Torvalds #endif 327*1da177e4SLinus Torvalds min_frame_size = LEC_MINIMUM_8023_SIZE; 328*1da177e4SLinus Torvalds if (skb->len < min_frame_size) { 329*1da177e4SLinus Torvalds if ((skb->len + skb_tailroom(skb)) < min_frame_size) { 330*1da177e4SLinus Torvalds skb2 = skb_copy_expand(skb, 0, 331*1da177e4SLinus Torvalds min_frame_size - skb->truesize, GFP_ATOMIC); 332*1da177e4SLinus Torvalds dev_kfree_skb(skb); 333*1da177e4SLinus Torvalds if (skb2 == NULL) { 334*1da177e4SLinus Torvalds priv->stats.tx_dropped++; 335*1da177e4SLinus Torvalds return 0; 336*1da177e4SLinus Torvalds } 337*1da177e4SLinus Torvalds skb = skb2; 338*1da177e4SLinus Torvalds } 339*1da177e4SLinus Torvalds skb_put(skb, min_frame_size - skb->len); 340*1da177e4SLinus Torvalds } 341*1da177e4SLinus Torvalds 342*1da177e4SLinus Torvalds /* Send to right vcc */ 343*1da177e4SLinus Torvalds is_rdesc = 0; 344*1da177e4SLinus Torvalds dst = lec_h->h_dest; 345*1da177e4SLinus Torvalds #ifdef CONFIG_TR 346*1da177e4SLinus Torvalds if (priv->is_trdev) { 347*1da177e4SLinus Torvalds dst = get_tr_dst(skb->data+2, rdesc); 348*1da177e4SLinus Torvalds if (dst == NULL) { 349*1da177e4SLinus Torvalds dst = rdesc; 350*1da177e4SLinus Torvalds is_rdesc = 1; 351*1da177e4SLinus Torvalds } 352*1da177e4SLinus Torvalds } 353*1da177e4SLinus Torvalds #endif 354*1da177e4SLinus Torvalds entry = NULL; 355*1da177e4SLinus Torvalds vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); 356*1da177e4SLinus Torvalds DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name, 357*1da177e4SLinus Torvalds vcc, vcc?vcc->flags:0, entry); 358*1da177e4SLinus Torvalds if (!vcc || !test_bit(ATM_VF_READY,&vcc->flags)) { 359*1da177e4SLinus Torvalds if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { 360*1da177e4SLinus Torvalds DPRINTK("%s:lec_start_xmit: queuing packet, ", dev->name); 361*1da177e4SLinus Torvalds DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", 362*1da177e4SLinus Torvalds lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], 363*1da177e4SLinus Torvalds lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); 364*1da177e4SLinus Torvalds skb_queue_tail(&entry->tx_wait, skb); 365*1da177e4SLinus Torvalds } else { 366*1da177e4SLinus Torvalds DPRINTK("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name); 367*1da177e4SLinus Torvalds DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", 368*1da177e4SLinus Torvalds lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], 369*1da177e4SLinus Torvalds lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); 370*1da177e4SLinus Torvalds priv->stats.tx_dropped++; 371*1da177e4SLinus Torvalds dev_kfree_skb(skb); 372*1da177e4SLinus Torvalds } 373*1da177e4SLinus Torvalds return 0; 374*1da177e4SLinus Torvalds } 375*1da177e4SLinus Torvalds 376*1da177e4SLinus Torvalds #if DUMP_PACKETS > 0 377*1da177e4SLinus Torvalds printk("%s:sending to vpi:%d vci:%d\n", dev->name, 378*1da177e4SLinus Torvalds vcc->vpi, vcc->vci); 379*1da177e4SLinus Torvalds #endif /* DUMP_PACKETS > 0 */ 380*1da177e4SLinus Torvalds 381*1da177e4SLinus Torvalds while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { 382*1da177e4SLinus Torvalds DPRINTK("lec.c: emptying tx queue, "); 383*1da177e4SLinus Torvalds DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", 384*1da177e4SLinus Torvalds lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], 385*1da177e4SLinus Torvalds lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); 386*1da177e4SLinus Torvalds lec_send(vcc, skb2, priv); 387*1da177e4SLinus Torvalds } 388*1da177e4SLinus Torvalds 389*1da177e4SLinus Torvalds lec_send(vcc, skb, priv); 390*1da177e4SLinus Torvalds 391*1da177e4SLinus Torvalds if (!atm_may_send(vcc, 0)) { 392*1da177e4SLinus Torvalds struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds vpriv->xoff = 1; 395*1da177e4SLinus Torvalds netif_stop_queue(dev); 396*1da177e4SLinus Torvalds 397*1da177e4SLinus Torvalds /* 398*1da177e4SLinus Torvalds * vcc->pop() might have occurred in between, making 399*1da177e4SLinus Torvalds * the vcc usuable again. Since xmit is serialized, 400*1da177e4SLinus Torvalds * this is the only situation we have to re-test. 401*1da177e4SLinus Torvalds */ 402*1da177e4SLinus Torvalds 403*1da177e4SLinus Torvalds if (atm_may_send(vcc, 0)) 404*1da177e4SLinus Torvalds netif_wake_queue(dev); 405*1da177e4SLinus Torvalds } 406*1da177e4SLinus Torvalds 407*1da177e4SLinus Torvalds dev->trans_start = jiffies; 408*1da177e4SLinus Torvalds return 0; 409*1da177e4SLinus Torvalds } 410*1da177e4SLinus Torvalds 411*1da177e4SLinus Torvalds /* The inverse routine to net_open(). */ 412*1da177e4SLinus Torvalds static int 413*1da177e4SLinus Torvalds lec_close(struct net_device *dev) 414*1da177e4SLinus Torvalds { 415*1da177e4SLinus Torvalds netif_stop_queue(dev); 416*1da177e4SLinus Torvalds return 0; 417*1da177e4SLinus Torvalds } 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds /* 420*1da177e4SLinus Torvalds * Get the current statistics. 421*1da177e4SLinus Torvalds * This may be called with the card open or closed. 422*1da177e4SLinus Torvalds */ 423*1da177e4SLinus Torvalds static struct net_device_stats * 424*1da177e4SLinus Torvalds lec_get_stats(struct net_device *dev) 425*1da177e4SLinus Torvalds { 426*1da177e4SLinus Torvalds return &((struct lec_priv *)dev->priv)->stats; 427*1da177e4SLinus Torvalds } 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds static int 430*1da177e4SLinus Torvalds lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) 431*1da177e4SLinus Torvalds { 432*1da177e4SLinus Torvalds unsigned long flags; 433*1da177e4SLinus Torvalds struct net_device *dev = (struct net_device*)vcc->proto_data; 434*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv*)dev->priv; 435*1da177e4SLinus Torvalds struct atmlec_msg *mesg; 436*1da177e4SLinus Torvalds struct lec_arp_table *entry; 437*1da177e4SLinus Torvalds int i; 438*1da177e4SLinus Torvalds char *tmp; /* FIXME */ 439*1da177e4SLinus Torvalds 440*1da177e4SLinus Torvalds atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); 441*1da177e4SLinus Torvalds mesg = (struct atmlec_msg *)skb->data; 442*1da177e4SLinus Torvalds tmp = skb->data; 443*1da177e4SLinus Torvalds tmp += sizeof(struct atmlec_msg); 444*1da177e4SLinus Torvalds DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type); 445*1da177e4SLinus Torvalds switch(mesg->type) { 446*1da177e4SLinus Torvalds case l_set_mac_addr: 447*1da177e4SLinus Torvalds for (i=0;i<6;i++) { 448*1da177e4SLinus Torvalds dev->dev_addr[i] = mesg->content.normal.mac_addr[i]; 449*1da177e4SLinus Torvalds } 450*1da177e4SLinus Torvalds break; 451*1da177e4SLinus Torvalds case l_del_mac_addr: 452*1da177e4SLinus Torvalds for(i=0;i<6;i++) { 453*1da177e4SLinus Torvalds dev->dev_addr[i] = 0; 454*1da177e4SLinus Torvalds } 455*1da177e4SLinus Torvalds break; 456*1da177e4SLinus Torvalds case l_addr_delete: 457*1da177e4SLinus Torvalds lec_addr_delete(priv, mesg->content.normal.atm_addr, 458*1da177e4SLinus Torvalds mesg->content.normal.flag); 459*1da177e4SLinus Torvalds break; 460*1da177e4SLinus Torvalds case l_topology_change: 461*1da177e4SLinus Torvalds priv->topology_change = mesg->content.normal.flag; 462*1da177e4SLinus Torvalds break; 463*1da177e4SLinus Torvalds case l_flush_complete: 464*1da177e4SLinus Torvalds lec_flush_complete(priv, mesg->content.normal.flag); 465*1da177e4SLinus Torvalds break; 466*1da177e4SLinus Torvalds case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */ 467*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 468*1da177e4SLinus Torvalds entry = lec_arp_find(priv, mesg->content.normal.mac_addr); 469*1da177e4SLinus Torvalds lec_arp_remove(priv, entry); 470*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 471*1da177e4SLinus Torvalds 472*1da177e4SLinus Torvalds if (mesg->content.normal.no_source_le_narp) 473*1da177e4SLinus Torvalds break; 474*1da177e4SLinus Torvalds /* FALL THROUGH */ 475*1da177e4SLinus Torvalds case l_arp_update: 476*1da177e4SLinus Torvalds lec_arp_update(priv, mesg->content.normal.mac_addr, 477*1da177e4SLinus Torvalds mesg->content.normal.atm_addr, 478*1da177e4SLinus Torvalds mesg->content.normal.flag, 479*1da177e4SLinus Torvalds mesg->content.normal.targetless_le_arp); 480*1da177e4SLinus Torvalds DPRINTK("lec: in l_arp_update\n"); 481*1da177e4SLinus Torvalds if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */ 482*1da177e4SLinus Torvalds DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n", mesg->sizeoftlvs); 483*1da177e4SLinus Torvalds lane2_associate_ind(dev, 484*1da177e4SLinus Torvalds mesg->content.normal.mac_addr, 485*1da177e4SLinus Torvalds tmp, mesg->sizeoftlvs); 486*1da177e4SLinus Torvalds } 487*1da177e4SLinus Torvalds break; 488*1da177e4SLinus Torvalds case l_config: 489*1da177e4SLinus Torvalds priv->maximum_unknown_frame_count = 490*1da177e4SLinus Torvalds mesg->content.config.maximum_unknown_frame_count; 491*1da177e4SLinus Torvalds priv->max_unknown_frame_time = 492*1da177e4SLinus Torvalds (mesg->content.config.max_unknown_frame_time*HZ); 493*1da177e4SLinus Torvalds priv->max_retry_count = 494*1da177e4SLinus Torvalds mesg->content.config.max_retry_count; 495*1da177e4SLinus Torvalds priv->aging_time = (mesg->content.config.aging_time*HZ); 496*1da177e4SLinus Torvalds priv->forward_delay_time = 497*1da177e4SLinus Torvalds (mesg->content.config.forward_delay_time*HZ); 498*1da177e4SLinus Torvalds priv->arp_response_time = 499*1da177e4SLinus Torvalds (mesg->content.config.arp_response_time*HZ); 500*1da177e4SLinus Torvalds priv->flush_timeout = (mesg->content.config.flush_timeout*HZ); 501*1da177e4SLinus Torvalds priv->path_switching_delay = 502*1da177e4SLinus Torvalds (mesg->content.config.path_switching_delay*HZ); 503*1da177e4SLinus Torvalds priv->lane_version = mesg->content.config.lane_version; /* LANE2 */ 504*1da177e4SLinus Torvalds priv->lane2_ops = NULL; 505*1da177e4SLinus Torvalds if (priv->lane_version > 1) 506*1da177e4SLinus Torvalds priv->lane2_ops = &lane2_ops; 507*1da177e4SLinus Torvalds if (dev->change_mtu(dev, mesg->content.config.mtu)) 508*1da177e4SLinus Torvalds printk("%s: change_mtu to %d failed\n", dev->name, 509*1da177e4SLinus Torvalds mesg->content.config.mtu); 510*1da177e4SLinus Torvalds priv->is_proxy = mesg->content.config.is_proxy; 511*1da177e4SLinus Torvalds break; 512*1da177e4SLinus Torvalds case l_flush_tran_id: 513*1da177e4SLinus Torvalds lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr, 514*1da177e4SLinus Torvalds mesg->content.normal.flag); 515*1da177e4SLinus Torvalds break; 516*1da177e4SLinus Torvalds case l_set_lecid: 517*1da177e4SLinus Torvalds priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag); 518*1da177e4SLinus Torvalds break; 519*1da177e4SLinus Torvalds case l_should_bridge: { 520*1da177e4SLinus Torvalds #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 521*1da177e4SLinus Torvalds struct net_bridge_fdb_entry *f; 522*1da177e4SLinus Torvalds 523*1da177e4SLinus Torvalds DPRINTK("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n", 524*1da177e4SLinus Torvalds dev->name, 525*1da177e4SLinus Torvalds mesg->content.proxy.mac_addr[0], mesg->content.proxy.mac_addr[1], 526*1da177e4SLinus Torvalds mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3], 527*1da177e4SLinus Torvalds mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]); 528*1da177e4SLinus Torvalds 529*1da177e4SLinus Torvalds if (br_fdb_get_hook == NULL || dev->br_port == NULL) 530*1da177e4SLinus Torvalds break; 531*1da177e4SLinus Torvalds 532*1da177e4SLinus Torvalds f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr); 533*1da177e4SLinus Torvalds if (f != NULL && 534*1da177e4SLinus Torvalds f->dst->dev != dev && 535*1da177e4SLinus Torvalds f->dst->state == BR_STATE_FORWARDING) { 536*1da177e4SLinus Torvalds /* hit from bridge table, send LE_ARP_RESPONSE */ 537*1da177e4SLinus Torvalds struct sk_buff *skb2; 538*1da177e4SLinus Torvalds struct sock *sk; 539*1da177e4SLinus Torvalds 540*1da177e4SLinus Torvalds DPRINTK("%s: entry found, responding to zeppelin\n", dev->name); 541*1da177e4SLinus Torvalds skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); 542*1da177e4SLinus Torvalds if (skb2 == NULL) { 543*1da177e4SLinus Torvalds br_fdb_put_hook(f); 544*1da177e4SLinus Torvalds break; 545*1da177e4SLinus Torvalds } 546*1da177e4SLinus Torvalds skb2->len = sizeof(struct atmlec_msg); 547*1da177e4SLinus Torvalds memcpy(skb2->data, mesg, sizeof(struct atmlec_msg)); 548*1da177e4SLinus Torvalds atm_force_charge(priv->lecd, skb2->truesize); 549*1da177e4SLinus Torvalds sk = sk_atm(priv->lecd); 550*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, skb2); 551*1da177e4SLinus Torvalds sk->sk_data_ready(sk, skb2->len); 552*1da177e4SLinus Torvalds } 553*1da177e4SLinus Torvalds if (f != NULL) br_fdb_put_hook(f); 554*1da177e4SLinus Torvalds #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ 555*1da177e4SLinus Torvalds } 556*1da177e4SLinus Torvalds break; 557*1da177e4SLinus Torvalds default: 558*1da177e4SLinus Torvalds printk("%s: Unknown message type %d\n", dev->name, mesg->type); 559*1da177e4SLinus Torvalds dev_kfree_skb(skb); 560*1da177e4SLinus Torvalds return -EINVAL; 561*1da177e4SLinus Torvalds } 562*1da177e4SLinus Torvalds dev_kfree_skb(skb); 563*1da177e4SLinus Torvalds return 0; 564*1da177e4SLinus Torvalds } 565*1da177e4SLinus Torvalds 566*1da177e4SLinus Torvalds static void 567*1da177e4SLinus Torvalds lec_atm_close(struct atm_vcc *vcc) 568*1da177e4SLinus Torvalds { 569*1da177e4SLinus Torvalds struct sk_buff *skb; 570*1da177e4SLinus Torvalds struct net_device *dev = (struct net_device *)vcc->proto_data; 571*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)dev->priv; 572*1da177e4SLinus Torvalds 573*1da177e4SLinus Torvalds priv->lecd = NULL; 574*1da177e4SLinus Torvalds /* Do something needful? */ 575*1da177e4SLinus Torvalds 576*1da177e4SLinus Torvalds netif_stop_queue(dev); 577*1da177e4SLinus Torvalds lec_arp_destroy(priv); 578*1da177e4SLinus Torvalds 579*1da177e4SLinus Torvalds if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) 580*1da177e4SLinus Torvalds printk("%s lec_atm_close: closing with messages pending\n", 581*1da177e4SLinus Torvalds dev->name); 582*1da177e4SLinus Torvalds while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) { 583*1da177e4SLinus Torvalds atm_return(vcc, skb->truesize); 584*1da177e4SLinus Torvalds dev_kfree_skb(skb); 585*1da177e4SLinus Torvalds } 586*1da177e4SLinus Torvalds 587*1da177e4SLinus Torvalds printk("%s: Shut down!\n", dev->name); 588*1da177e4SLinus Torvalds module_put(THIS_MODULE); 589*1da177e4SLinus Torvalds } 590*1da177e4SLinus Torvalds 591*1da177e4SLinus Torvalds static struct atmdev_ops lecdev_ops = { 592*1da177e4SLinus Torvalds .close = lec_atm_close, 593*1da177e4SLinus Torvalds .send = lec_atm_send 594*1da177e4SLinus Torvalds }; 595*1da177e4SLinus Torvalds 596*1da177e4SLinus Torvalds static struct atm_dev lecatm_dev = { 597*1da177e4SLinus Torvalds .ops = &lecdev_ops, 598*1da177e4SLinus Torvalds .type = "lec", 599*1da177e4SLinus Torvalds .number = 999, /* dummy device number */ 600*1da177e4SLinus Torvalds .lock = SPIN_LOCK_UNLOCKED 601*1da177e4SLinus Torvalds }; 602*1da177e4SLinus Torvalds 603*1da177e4SLinus Torvalds /* 604*1da177e4SLinus Torvalds * LANE2: new argument struct sk_buff *data contains 605*1da177e4SLinus Torvalds * the LE_ARP based TLVs introduced in the LANE2 spec 606*1da177e4SLinus Torvalds */ 607*1da177e4SLinus Torvalds static int 608*1da177e4SLinus Torvalds send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, 609*1da177e4SLinus Torvalds unsigned char *mac_addr, unsigned char *atm_addr, 610*1da177e4SLinus Torvalds struct sk_buff *data) 611*1da177e4SLinus Torvalds { 612*1da177e4SLinus Torvalds struct sock *sk; 613*1da177e4SLinus Torvalds struct sk_buff *skb; 614*1da177e4SLinus Torvalds struct atmlec_msg *mesg; 615*1da177e4SLinus Torvalds 616*1da177e4SLinus Torvalds if (!priv || !priv->lecd) { 617*1da177e4SLinus Torvalds return -1; 618*1da177e4SLinus Torvalds } 619*1da177e4SLinus Torvalds skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); 620*1da177e4SLinus Torvalds if (!skb) 621*1da177e4SLinus Torvalds return -1; 622*1da177e4SLinus Torvalds skb->len = sizeof(struct atmlec_msg); 623*1da177e4SLinus Torvalds mesg = (struct atmlec_msg *)skb->data; 624*1da177e4SLinus Torvalds memset(mesg, 0, sizeof(struct atmlec_msg)); 625*1da177e4SLinus Torvalds mesg->type = type; 626*1da177e4SLinus Torvalds if (data != NULL) 627*1da177e4SLinus Torvalds mesg->sizeoftlvs = data->len; 628*1da177e4SLinus Torvalds if (mac_addr) 629*1da177e4SLinus Torvalds memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN); 630*1da177e4SLinus Torvalds else 631*1da177e4SLinus Torvalds mesg->content.normal.targetless_le_arp = 1; 632*1da177e4SLinus Torvalds if (atm_addr) 633*1da177e4SLinus Torvalds memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); 634*1da177e4SLinus Torvalds 635*1da177e4SLinus Torvalds atm_force_charge(priv->lecd, skb->truesize); 636*1da177e4SLinus Torvalds sk = sk_atm(priv->lecd); 637*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, skb); 638*1da177e4SLinus Torvalds sk->sk_data_ready(sk, skb->len); 639*1da177e4SLinus Torvalds 640*1da177e4SLinus Torvalds if (data != NULL) { 641*1da177e4SLinus Torvalds DPRINTK("lec: about to send %d bytes of data\n", data->len); 642*1da177e4SLinus Torvalds atm_force_charge(priv->lecd, data->truesize); 643*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, data); 644*1da177e4SLinus Torvalds sk->sk_data_ready(sk, skb->len); 645*1da177e4SLinus Torvalds } 646*1da177e4SLinus Torvalds 647*1da177e4SLinus Torvalds return 0; 648*1da177e4SLinus Torvalds } 649*1da177e4SLinus Torvalds 650*1da177e4SLinus Torvalds /* shamelessly stolen from drivers/net/net_init.c */ 651*1da177e4SLinus Torvalds static int lec_change_mtu(struct net_device *dev, int new_mtu) 652*1da177e4SLinus Torvalds { 653*1da177e4SLinus Torvalds if ((new_mtu < 68) || (new_mtu > 18190)) 654*1da177e4SLinus Torvalds return -EINVAL; 655*1da177e4SLinus Torvalds dev->mtu = new_mtu; 656*1da177e4SLinus Torvalds return 0; 657*1da177e4SLinus Torvalds } 658*1da177e4SLinus Torvalds 659*1da177e4SLinus Torvalds static void lec_set_multicast_list(struct net_device *dev) 660*1da177e4SLinus Torvalds { 661*1da177e4SLinus Torvalds /* by default, all multicast frames arrive over the bus. 662*1da177e4SLinus Torvalds * eventually support selective multicast service 663*1da177e4SLinus Torvalds */ 664*1da177e4SLinus Torvalds return; 665*1da177e4SLinus Torvalds } 666*1da177e4SLinus Torvalds 667*1da177e4SLinus Torvalds static void 668*1da177e4SLinus Torvalds lec_init(struct net_device *dev) 669*1da177e4SLinus Torvalds { 670*1da177e4SLinus Torvalds dev->change_mtu = lec_change_mtu; 671*1da177e4SLinus Torvalds dev->open = lec_open; 672*1da177e4SLinus Torvalds dev->stop = lec_close; 673*1da177e4SLinus Torvalds dev->hard_start_xmit = lec_start_xmit; 674*1da177e4SLinus Torvalds dev->tx_timeout = lec_tx_timeout; 675*1da177e4SLinus Torvalds 676*1da177e4SLinus Torvalds dev->get_stats = lec_get_stats; 677*1da177e4SLinus Torvalds dev->set_multicast_list = lec_set_multicast_list; 678*1da177e4SLinus Torvalds dev->do_ioctl = NULL; 679*1da177e4SLinus Torvalds printk("%s: Initialized!\n",dev->name); 680*1da177e4SLinus Torvalds return; 681*1da177e4SLinus Torvalds } 682*1da177e4SLinus Torvalds 683*1da177e4SLinus Torvalds static unsigned char lec_ctrl_magic[] = { 684*1da177e4SLinus Torvalds 0xff, 685*1da177e4SLinus Torvalds 0x00, 686*1da177e4SLinus Torvalds 0x01, 687*1da177e4SLinus Torvalds 0x01 }; 688*1da177e4SLinus Torvalds 689*1da177e4SLinus Torvalds static void 690*1da177e4SLinus Torvalds lec_push(struct atm_vcc *vcc, struct sk_buff *skb) 691*1da177e4SLinus Torvalds { 692*1da177e4SLinus Torvalds struct net_device *dev = (struct net_device *)vcc->proto_data; 693*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)dev->priv; 694*1da177e4SLinus Torvalds 695*1da177e4SLinus Torvalds #if DUMP_PACKETS >0 696*1da177e4SLinus Torvalds int i=0; 697*1da177e4SLinus Torvalds char buf[300]; 698*1da177e4SLinus Torvalds 699*1da177e4SLinus Torvalds printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name, 700*1da177e4SLinus Torvalds vcc->vpi, vcc->vci); 701*1da177e4SLinus Torvalds #endif 702*1da177e4SLinus Torvalds if (!skb) { 703*1da177e4SLinus Torvalds DPRINTK("%s: null skb\n",dev->name); 704*1da177e4SLinus Torvalds lec_vcc_close(priv, vcc); 705*1da177e4SLinus Torvalds return; 706*1da177e4SLinus Torvalds } 707*1da177e4SLinus Torvalds #if DUMP_PACKETS > 0 708*1da177e4SLinus Torvalds printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name, 709*1da177e4SLinus Torvalds skb->len, priv->lecid); 710*1da177e4SLinus Torvalds #if DUMP_PACKETS >= 2 711*1da177e4SLinus Torvalds for(i=0;i<skb->len && i <99;i++) { 712*1da177e4SLinus Torvalds sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); 713*1da177e4SLinus Torvalds } 714*1da177e4SLinus Torvalds #elif DUMP_PACKETS >= 1 715*1da177e4SLinus Torvalds for(i=0;i<skb->len && i < 30;i++) { 716*1da177e4SLinus Torvalds sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); 717*1da177e4SLinus Torvalds } 718*1da177e4SLinus Torvalds #endif /* DUMP_PACKETS >= 1 */ 719*1da177e4SLinus Torvalds if (i==skb->len) 720*1da177e4SLinus Torvalds printk("%s\n",buf); 721*1da177e4SLinus Torvalds else 722*1da177e4SLinus Torvalds printk("%s...\n",buf); 723*1da177e4SLinus Torvalds #endif /* DUMP_PACKETS > 0 */ 724*1da177e4SLinus Torvalds if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/ 725*1da177e4SLinus Torvalds struct sock *sk = sk_atm(vcc); 726*1da177e4SLinus Torvalds 727*1da177e4SLinus Torvalds DPRINTK("%s: To daemon\n",dev->name); 728*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, skb); 729*1da177e4SLinus Torvalds sk->sk_data_ready(sk, skb->len); 730*1da177e4SLinus Torvalds } else { /* Data frame, queue to protocol handlers */ 731*1da177e4SLinus Torvalds unsigned char *dst; 732*1da177e4SLinus Torvalds 733*1da177e4SLinus Torvalds atm_return(vcc,skb->truesize); 734*1da177e4SLinus Torvalds if (*(uint16_t *)skb->data == htons(priv->lecid) || 735*1da177e4SLinus Torvalds !priv->lecd || 736*1da177e4SLinus Torvalds !(dev->flags & IFF_UP)) { 737*1da177e4SLinus Torvalds /* Probably looping back, or if lecd is missing, 738*1da177e4SLinus Torvalds lecd has gone down */ 739*1da177e4SLinus Torvalds DPRINTK("Ignoring frame...\n"); 740*1da177e4SLinus Torvalds dev_kfree_skb(skb); 741*1da177e4SLinus Torvalds return; 742*1da177e4SLinus Torvalds } 743*1da177e4SLinus Torvalds #ifdef CONFIG_TR 744*1da177e4SLinus Torvalds if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest; 745*1da177e4SLinus Torvalds else 746*1da177e4SLinus Torvalds #endif 747*1da177e4SLinus Torvalds dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest; 748*1da177e4SLinus Torvalds 749*1da177e4SLinus Torvalds if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ 750*1da177e4SLinus Torvalds !priv->is_proxy && /* Proxy wants all the packets */ 751*1da177e4SLinus Torvalds memcmp(dst, dev->dev_addr, dev->addr_len)) { 752*1da177e4SLinus Torvalds dev_kfree_skb(skb); 753*1da177e4SLinus Torvalds return; 754*1da177e4SLinus Torvalds } 755*1da177e4SLinus Torvalds if (priv->lec_arp_empty_ones) { 756*1da177e4SLinus Torvalds lec_arp_check_empties(priv, vcc, skb); 757*1da177e4SLinus Torvalds } 758*1da177e4SLinus Torvalds skb->dev = dev; 759*1da177e4SLinus Torvalds skb_pull(skb, 2); /* skip lec_id */ 760*1da177e4SLinus Torvalds #ifdef CONFIG_TR 761*1da177e4SLinus Torvalds if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev); 762*1da177e4SLinus Torvalds else 763*1da177e4SLinus Torvalds #endif 764*1da177e4SLinus Torvalds skb->protocol = eth_type_trans(skb, dev); 765*1da177e4SLinus Torvalds priv->stats.rx_packets++; 766*1da177e4SLinus Torvalds priv->stats.rx_bytes += skb->len; 767*1da177e4SLinus Torvalds memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); 768*1da177e4SLinus Torvalds netif_rx(skb); 769*1da177e4SLinus Torvalds } 770*1da177e4SLinus Torvalds } 771*1da177e4SLinus Torvalds 772*1da177e4SLinus Torvalds static void 773*1da177e4SLinus Torvalds lec_pop(struct atm_vcc *vcc, struct sk_buff *skb) 774*1da177e4SLinus Torvalds { 775*1da177e4SLinus Torvalds struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); 776*1da177e4SLinus Torvalds struct net_device *dev = skb->dev; 777*1da177e4SLinus Torvalds 778*1da177e4SLinus Torvalds if (vpriv == NULL) { 779*1da177e4SLinus Torvalds printk("lec_pop(): vpriv = NULL!?!?!?\n"); 780*1da177e4SLinus Torvalds return; 781*1da177e4SLinus Torvalds } 782*1da177e4SLinus Torvalds 783*1da177e4SLinus Torvalds vpriv->old_pop(vcc, skb); 784*1da177e4SLinus Torvalds 785*1da177e4SLinus Torvalds if (vpriv->xoff && atm_may_send(vcc, 0)) { 786*1da177e4SLinus Torvalds vpriv->xoff = 0; 787*1da177e4SLinus Torvalds if (netif_running(dev) && netif_queue_stopped(dev)) 788*1da177e4SLinus Torvalds netif_wake_queue(dev); 789*1da177e4SLinus Torvalds } 790*1da177e4SLinus Torvalds } 791*1da177e4SLinus Torvalds 792*1da177e4SLinus Torvalds static int 793*1da177e4SLinus Torvalds lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) 794*1da177e4SLinus Torvalds { 795*1da177e4SLinus Torvalds struct lec_vcc_priv *vpriv; 796*1da177e4SLinus Torvalds int bytes_left; 797*1da177e4SLinus Torvalds struct atmlec_ioc ioc_data; 798*1da177e4SLinus Torvalds 799*1da177e4SLinus Torvalds /* Lecd must be up in this case */ 800*1da177e4SLinus Torvalds bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); 801*1da177e4SLinus Torvalds if (bytes_left != 0) { 802*1da177e4SLinus Torvalds printk("lec: lec_vcc_attach, copy from user failed for %d bytes\n", 803*1da177e4SLinus Torvalds bytes_left); 804*1da177e4SLinus Torvalds } 805*1da177e4SLinus Torvalds if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || 806*1da177e4SLinus Torvalds !dev_lec[ioc_data.dev_num]) 807*1da177e4SLinus Torvalds return -EINVAL; 808*1da177e4SLinus Torvalds if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) 809*1da177e4SLinus Torvalds return -ENOMEM; 810*1da177e4SLinus Torvalds vpriv->xoff = 0; 811*1da177e4SLinus Torvalds vpriv->old_pop = vcc->pop; 812*1da177e4SLinus Torvalds vcc->user_back = vpriv; 813*1da177e4SLinus Torvalds vcc->pop = lec_pop; 814*1da177e4SLinus Torvalds lec_vcc_added(dev_lec[ioc_data.dev_num]->priv, 815*1da177e4SLinus Torvalds &ioc_data, vcc, vcc->push); 816*1da177e4SLinus Torvalds vcc->proto_data = dev_lec[ioc_data.dev_num]; 817*1da177e4SLinus Torvalds vcc->push = lec_push; 818*1da177e4SLinus Torvalds return 0; 819*1da177e4SLinus Torvalds } 820*1da177e4SLinus Torvalds 821*1da177e4SLinus Torvalds static int 822*1da177e4SLinus Torvalds lec_mcast_attach(struct atm_vcc *vcc, int arg) 823*1da177e4SLinus Torvalds { 824*1da177e4SLinus Torvalds if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg]) 825*1da177e4SLinus Torvalds return -EINVAL; 826*1da177e4SLinus Torvalds vcc->proto_data = dev_lec[arg]; 827*1da177e4SLinus Torvalds return (lec_mcast_make((struct lec_priv*)dev_lec[arg]->priv, vcc)); 828*1da177e4SLinus Torvalds } 829*1da177e4SLinus Torvalds 830*1da177e4SLinus Torvalds /* Initialize device. */ 831*1da177e4SLinus Torvalds static int 832*1da177e4SLinus Torvalds lecd_attach(struct atm_vcc *vcc, int arg) 833*1da177e4SLinus Torvalds { 834*1da177e4SLinus Torvalds int i; 835*1da177e4SLinus Torvalds struct lec_priv *priv; 836*1da177e4SLinus Torvalds 837*1da177e4SLinus Torvalds if (arg<0) 838*1da177e4SLinus Torvalds i = 0; 839*1da177e4SLinus Torvalds else 840*1da177e4SLinus Torvalds i = arg; 841*1da177e4SLinus Torvalds #ifdef CONFIG_TR 842*1da177e4SLinus Torvalds if (arg >= MAX_LEC_ITF) 843*1da177e4SLinus Torvalds return -EINVAL; 844*1da177e4SLinus Torvalds #else /* Reserve the top NUM_TR_DEVS for TR */ 845*1da177e4SLinus Torvalds if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS)) 846*1da177e4SLinus Torvalds return -EINVAL; 847*1da177e4SLinus Torvalds #endif 848*1da177e4SLinus Torvalds if (!dev_lec[i]) { 849*1da177e4SLinus Torvalds int is_trdev, size; 850*1da177e4SLinus Torvalds 851*1da177e4SLinus Torvalds is_trdev = 0; 852*1da177e4SLinus Torvalds if (i >= (MAX_LEC_ITF - NUM_TR_DEVS)) 853*1da177e4SLinus Torvalds is_trdev = 1; 854*1da177e4SLinus Torvalds 855*1da177e4SLinus Torvalds size = sizeof(struct lec_priv); 856*1da177e4SLinus Torvalds #ifdef CONFIG_TR 857*1da177e4SLinus Torvalds if (is_trdev) 858*1da177e4SLinus Torvalds dev_lec[i] = alloc_trdev(size); 859*1da177e4SLinus Torvalds else 860*1da177e4SLinus Torvalds #endif 861*1da177e4SLinus Torvalds dev_lec[i] = alloc_etherdev(size); 862*1da177e4SLinus Torvalds if (!dev_lec[i]) 863*1da177e4SLinus Torvalds return -ENOMEM; 864*1da177e4SLinus Torvalds snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i); 865*1da177e4SLinus Torvalds if (register_netdev(dev_lec[i])) { 866*1da177e4SLinus Torvalds free_netdev(dev_lec[i]); 867*1da177e4SLinus Torvalds return -EINVAL; 868*1da177e4SLinus Torvalds } 869*1da177e4SLinus Torvalds 870*1da177e4SLinus Torvalds priv = dev_lec[i]->priv; 871*1da177e4SLinus Torvalds priv->is_trdev = is_trdev; 872*1da177e4SLinus Torvalds lec_init(dev_lec[i]); 873*1da177e4SLinus Torvalds } else { 874*1da177e4SLinus Torvalds priv = dev_lec[i]->priv; 875*1da177e4SLinus Torvalds if (priv->lecd) 876*1da177e4SLinus Torvalds return -EADDRINUSE; 877*1da177e4SLinus Torvalds } 878*1da177e4SLinus Torvalds lec_arp_init(priv); 879*1da177e4SLinus Torvalds priv->itfnum = i; /* LANE2 addition */ 880*1da177e4SLinus Torvalds priv->lecd = vcc; 881*1da177e4SLinus Torvalds vcc->dev = &lecatm_dev; 882*1da177e4SLinus Torvalds vcc_insert_socket(sk_atm(vcc)); 883*1da177e4SLinus Torvalds 884*1da177e4SLinus Torvalds vcc->proto_data = dev_lec[i]; 885*1da177e4SLinus Torvalds set_bit(ATM_VF_META,&vcc->flags); 886*1da177e4SLinus Torvalds set_bit(ATM_VF_READY,&vcc->flags); 887*1da177e4SLinus Torvalds 888*1da177e4SLinus Torvalds /* Set default values to these variables */ 889*1da177e4SLinus Torvalds priv->maximum_unknown_frame_count = 1; 890*1da177e4SLinus Torvalds priv->max_unknown_frame_time = (1*HZ); 891*1da177e4SLinus Torvalds priv->vcc_timeout_period = (1200*HZ); 892*1da177e4SLinus Torvalds priv->max_retry_count = 1; 893*1da177e4SLinus Torvalds priv->aging_time = (300*HZ); 894*1da177e4SLinus Torvalds priv->forward_delay_time = (15*HZ); 895*1da177e4SLinus Torvalds priv->topology_change = 0; 896*1da177e4SLinus Torvalds priv->arp_response_time = (1*HZ); 897*1da177e4SLinus Torvalds priv->flush_timeout = (4*HZ); 898*1da177e4SLinus Torvalds priv->path_switching_delay = (6*HZ); 899*1da177e4SLinus Torvalds 900*1da177e4SLinus Torvalds if (dev_lec[i]->flags & IFF_UP) { 901*1da177e4SLinus Torvalds netif_start_queue(dev_lec[i]); 902*1da177e4SLinus Torvalds } 903*1da177e4SLinus Torvalds __module_get(THIS_MODULE); 904*1da177e4SLinus Torvalds return i; 905*1da177e4SLinus Torvalds } 906*1da177e4SLinus Torvalds 907*1da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 908*1da177e4SLinus Torvalds static char* lec_arp_get_status_string(unsigned char status) 909*1da177e4SLinus Torvalds { 910*1da177e4SLinus Torvalds static char *lec_arp_status_string[] = { 911*1da177e4SLinus Torvalds "ESI_UNKNOWN ", 912*1da177e4SLinus Torvalds "ESI_ARP_PENDING ", 913*1da177e4SLinus Torvalds "ESI_VC_PENDING ", 914*1da177e4SLinus Torvalds "<Undefined> ", 915*1da177e4SLinus Torvalds "ESI_FLUSH_PENDING ", 916*1da177e4SLinus Torvalds "ESI_FORWARD_DIRECT" 917*1da177e4SLinus Torvalds }; 918*1da177e4SLinus Torvalds 919*1da177e4SLinus Torvalds if (status > ESI_FORWARD_DIRECT) 920*1da177e4SLinus Torvalds status = 3; /* ESI_UNDEFINED */ 921*1da177e4SLinus Torvalds return lec_arp_status_string[status]; 922*1da177e4SLinus Torvalds } 923*1da177e4SLinus Torvalds 924*1da177e4SLinus Torvalds static void lec_info(struct seq_file *seq, struct lec_arp_table *entry) 925*1da177e4SLinus Torvalds { 926*1da177e4SLinus Torvalds int i; 927*1da177e4SLinus Torvalds 928*1da177e4SLinus Torvalds for (i = 0; i < ETH_ALEN; i++) 929*1da177e4SLinus Torvalds seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff); 930*1da177e4SLinus Torvalds seq_printf(seq, " "); 931*1da177e4SLinus Torvalds for (i = 0; i < ATM_ESA_LEN; i++) 932*1da177e4SLinus Torvalds seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff); 933*1da177e4SLinus Torvalds seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status), 934*1da177e4SLinus Torvalds entry->flags & 0xffff); 935*1da177e4SLinus Torvalds if (entry->vcc) 936*1da177e4SLinus Torvalds seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci); 937*1da177e4SLinus Torvalds else 938*1da177e4SLinus Torvalds seq_printf(seq, " "); 939*1da177e4SLinus Torvalds if (entry->recv_vcc) { 940*1da177e4SLinus Torvalds seq_printf(seq, " %3d %3d", entry->recv_vcc->vpi, 941*1da177e4SLinus Torvalds entry->recv_vcc->vci); 942*1da177e4SLinus Torvalds } 943*1da177e4SLinus Torvalds seq_putc(seq, '\n'); 944*1da177e4SLinus Torvalds } 945*1da177e4SLinus Torvalds 946*1da177e4SLinus Torvalds 947*1da177e4SLinus Torvalds struct lec_state { 948*1da177e4SLinus Torvalds unsigned long flags; 949*1da177e4SLinus Torvalds struct lec_priv *locked; 950*1da177e4SLinus Torvalds struct lec_arp_table *entry; 951*1da177e4SLinus Torvalds struct net_device *dev; 952*1da177e4SLinus Torvalds int itf; 953*1da177e4SLinus Torvalds int arp_table; 954*1da177e4SLinus Torvalds int misc_table; 955*1da177e4SLinus Torvalds }; 956*1da177e4SLinus Torvalds 957*1da177e4SLinus Torvalds static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl, 958*1da177e4SLinus Torvalds loff_t *l) 959*1da177e4SLinus Torvalds { 960*1da177e4SLinus Torvalds struct lec_arp_table *e = state->entry; 961*1da177e4SLinus Torvalds 962*1da177e4SLinus Torvalds if (!e) 963*1da177e4SLinus Torvalds e = tbl; 964*1da177e4SLinus Torvalds if (e == (void *)1) { 965*1da177e4SLinus Torvalds e = tbl; 966*1da177e4SLinus Torvalds --*l; 967*1da177e4SLinus Torvalds } 968*1da177e4SLinus Torvalds for (; e; e = e->next) { 969*1da177e4SLinus Torvalds if (--*l < 0) 970*1da177e4SLinus Torvalds break; 971*1da177e4SLinus Torvalds } 972*1da177e4SLinus Torvalds state->entry = e; 973*1da177e4SLinus Torvalds return (*l < 0) ? state : NULL; 974*1da177e4SLinus Torvalds } 975*1da177e4SLinus Torvalds 976*1da177e4SLinus Torvalds static void *lec_arp_walk(struct lec_state *state, loff_t *l, 977*1da177e4SLinus Torvalds struct lec_priv *priv) 978*1da177e4SLinus Torvalds { 979*1da177e4SLinus Torvalds void *v = NULL; 980*1da177e4SLinus Torvalds int p; 981*1da177e4SLinus Torvalds 982*1da177e4SLinus Torvalds for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) { 983*1da177e4SLinus Torvalds v = lec_tbl_walk(state, priv->lec_arp_tables[p], l); 984*1da177e4SLinus Torvalds if (v) 985*1da177e4SLinus Torvalds break; 986*1da177e4SLinus Torvalds } 987*1da177e4SLinus Torvalds state->arp_table = p; 988*1da177e4SLinus Torvalds return v; 989*1da177e4SLinus Torvalds } 990*1da177e4SLinus Torvalds 991*1da177e4SLinus Torvalds static void *lec_misc_walk(struct lec_state *state, loff_t *l, 992*1da177e4SLinus Torvalds struct lec_priv *priv) 993*1da177e4SLinus Torvalds { 994*1da177e4SLinus Torvalds struct lec_arp_table *lec_misc_tables[] = { 995*1da177e4SLinus Torvalds priv->lec_arp_empty_ones, 996*1da177e4SLinus Torvalds priv->lec_no_forward, 997*1da177e4SLinus Torvalds priv->mcast_fwds 998*1da177e4SLinus Torvalds }; 999*1da177e4SLinus Torvalds void *v = NULL; 1000*1da177e4SLinus Torvalds int q; 1001*1da177e4SLinus Torvalds 1002*1da177e4SLinus Torvalds for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) { 1003*1da177e4SLinus Torvalds v = lec_tbl_walk(state, lec_misc_tables[q], l); 1004*1da177e4SLinus Torvalds if (v) 1005*1da177e4SLinus Torvalds break; 1006*1da177e4SLinus Torvalds } 1007*1da177e4SLinus Torvalds state->misc_table = q; 1008*1da177e4SLinus Torvalds return v; 1009*1da177e4SLinus Torvalds } 1010*1da177e4SLinus Torvalds 1011*1da177e4SLinus Torvalds static void *lec_priv_walk(struct lec_state *state, loff_t *l, 1012*1da177e4SLinus Torvalds struct lec_priv *priv) 1013*1da177e4SLinus Torvalds { 1014*1da177e4SLinus Torvalds if (!state->locked) { 1015*1da177e4SLinus Torvalds state->locked = priv; 1016*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, state->flags); 1017*1da177e4SLinus Torvalds } 1018*1da177e4SLinus Torvalds if (!lec_arp_walk(state, l, priv) && 1019*1da177e4SLinus Torvalds !lec_misc_walk(state, l, priv)) { 1020*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags); 1021*1da177e4SLinus Torvalds state->locked = NULL; 1022*1da177e4SLinus Torvalds /* Partial state reset for the next time we get called */ 1023*1da177e4SLinus Torvalds state->arp_table = state->misc_table = 0; 1024*1da177e4SLinus Torvalds } 1025*1da177e4SLinus Torvalds return state->locked; 1026*1da177e4SLinus Torvalds } 1027*1da177e4SLinus Torvalds 1028*1da177e4SLinus Torvalds static void *lec_itf_walk(struct lec_state *state, loff_t *l) 1029*1da177e4SLinus Torvalds { 1030*1da177e4SLinus Torvalds struct net_device *dev; 1031*1da177e4SLinus Torvalds void *v; 1032*1da177e4SLinus Torvalds 1033*1da177e4SLinus Torvalds dev = state->dev ? state->dev : dev_lec[state->itf]; 1034*1da177e4SLinus Torvalds v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL; 1035*1da177e4SLinus Torvalds if (!v && dev) { 1036*1da177e4SLinus Torvalds dev_put(dev); 1037*1da177e4SLinus Torvalds /* Partial state reset for the next time we get called */ 1038*1da177e4SLinus Torvalds dev = NULL; 1039*1da177e4SLinus Torvalds } 1040*1da177e4SLinus Torvalds state->dev = dev; 1041*1da177e4SLinus Torvalds return v; 1042*1da177e4SLinus Torvalds } 1043*1da177e4SLinus Torvalds 1044*1da177e4SLinus Torvalds static void *lec_get_idx(struct lec_state *state, loff_t l) 1045*1da177e4SLinus Torvalds { 1046*1da177e4SLinus Torvalds void *v = NULL; 1047*1da177e4SLinus Torvalds 1048*1da177e4SLinus Torvalds for (; state->itf < MAX_LEC_ITF; state->itf++) { 1049*1da177e4SLinus Torvalds v = lec_itf_walk(state, &l); 1050*1da177e4SLinus Torvalds if (v) 1051*1da177e4SLinus Torvalds break; 1052*1da177e4SLinus Torvalds } 1053*1da177e4SLinus Torvalds return v; 1054*1da177e4SLinus Torvalds } 1055*1da177e4SLinus Torvalds 1056*1da177e4SLinus Torvalds static void *lec_seq_start(struct seq_file *seq, loff_t *pos) 1057*1da177e4SLinus Torvalds { 1058*1da177e4SLinus Torvalds struct lec_state *state = seq->private; 1059*1da177e4SLinus Torvalds 1060*1da177e4SLinus Torvalds state->itf = 0; 1061*1da177e4SLinus Torvalds state->dev = NULL; 1062*1da177e4SLinus Torvalds state->locked = NULL; 1063*1da177e4SLinus Torvalds state->arp_table = 0; 1064*1da177e4SLinus Torvalds state->misc_table = 0; 1065*1da177e4SLinus Torvalds state->entry = (void *)1; 1066*1da177e4SLinus Torvalds 1067*1da177e4SLinus Torvalds return *pos ? lec_get_idx(state, *pos) : (void*)1; 1068*1da177e4SLinus Torvalds } 1069*1da177e4SLinus Torvalds 1070*1da177e4SLinus Torvalds static void lec_seq_stop(struct seq_file *seq, void *v) 1071*1da177e4SLinus Torvalds { 1072*1da177e4SLinus Torvalds struct lec_state *state = seq->private; 1073*1da177e4SLinus Torvalds 1074*1da177e4SLinus Torvalds if (state->dev) { 1075*1da177e4SLinus Torvalds spin_unlock_irqrestore(&state->locked->lec_arp_lock, 1076*1da177e4SLinus Torvalds state->flags); 1077*1da177e4SLinus Torvalds dev_put(state->dev); 1078*1da177e4SLinus Torvalds } 1079*1da177e4SLinus Torvalds } 1080*1da177e4SLinus Torvalds 1081*1da177e4SLinus Torvalds static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos) 1082*1da177e4SLinus Torvalds { 1083*1da177e4SLinus Torvalds struct lec_state *state = seq->private; 1084*1da177e4SLinus Torvalds 1085*1da177e4SLinus Torvalds v = lec_get_idx(state, 1); 1086*1da177e4SLinus Torvalds *pos += !!PTR_ERR(v); 1087*1da177e4SLinus Torvalds return v; 1088*1da177e4SLinus Torvalds } 1089*1da177e4SLinus Torvalds 1090*1da177e4SLinus Torvalds static int lec_seq_show(struct seq_file *seq, void *v) 1091*1da177e4SLinus Torvalds { 1092*1da177e4SLinus Torvalds static char lec_banner[] = "Itf MAC ATM destination" 1093*1da177e4SLinus Torvalds " Status Flags " 1094*1da177e4SLinus Torvalds "VPI/VCI Recv VPI/VCI\n"; 1095*1da177e4SLinus Torvalds 1096*1da177e4SLinus Torvalds if (v == (void *)1) 1097*1da177e4SLinus Torvalds seq_puts(seq, lec_banner); 1098*1da177e4SLinus Torvalds else { 1099*1da177e4SLinus Torvalds struct lec_state *state = seq->private; 1100*1da177e4SLinus Torvalds struct net_device *dev = state->dev; 1101*1da177e4SLinus Torvalds 1102*1da177e4SLinus Torvalds seq_printf(seq, "%s ", dev->name); 1103*1da177e4SLinus Torvalds lec_info(seq, state->entry); 1104*1da177e4SLinus Torvalds } 1105*1da177e4SLinus Torvalds return 0; 1106*1da177e4SLinus Torvalds } 1107*1da177e4SLinus Torvalds 1108*1da177e4SLinus Torvalds static struct seq_operations lec_seq_ops = { 1109*1da177e4SLinus Torvalds .start = lec_seq_start, 1110*1da177e4SLinus Torvalds .next = lec_seq_next, 1111*1da177e4SLinus Torvalds .stop = lec_seq_stop, 1112*1da177e4SLinus Torvalds .show = lec_seq_show, 1113*1da177e4SLinus Torvalds }; 1114*1da177e4SLinus Torvalds 1115*1da177e4SLinus Torvalds static int lec_seq_open(struct inode *inode, struct file *file) 1116*1da177e4SLinus Torvalds { 1117*1da177e4SLinus Torvalds struct lec_state *state; 1118*1da177e4SLinus Torvalds struct seq_file *seq; 1119*1da177e4SLinus Torvalds int rc = -EAGAIN; 1120*1da177e4SLinus Torvalds 1121*1da177e4SLinus Torvalds state = kmalloc(sizeof(*state), GFP_KERNEL); 1122*1da177e4SLinus Torvalds if (!state) { 1123*1da177e4SLinus Torvalds rc = -ENOMEM; 1124*1da177e4SLinus Torvalds goto out; 1125*1da177e4SLinus Torvalds } 1126*1da177e4SLinus Torvalds 1127*1da177e4SLinus Torvalds rc = seq_open(file, &lec_seq_ops); 1128*1da177e4SLinus Torvalds if (rc) 1129*1da177e4SLinus Torvalds goto out_kfree; 1130*1da177e4SLinus Torvalds seq = file->private_data; 1131*1da177e4SLinus Torvalds seq->private = state; 1132*1da177e4SLinus Torvalds out: 1133*1da177e4SLinus Torvalds return rc; 1134*1da177e4SLinus Torvalds 1135*1da177e4SLinus Torvalds out_kfree: 1136*1da177e4SLinus Torvalds kfree(state); 1137*1da177e4SLinus Torvalds goto out; 1138*1da177e4SLinus Torvalds } 1139*1da177e4SLinus Torvalds 1140*1da177e4SLinus Torvalds static int lec_seq_release(struct inode *inode, struct file *file) 1141*1da177e4SLinus Torvalds { 1142*1da177e4SLinus Torvalds return seq_release_private(inode, file); 1143*1da177e4SLinus Torvalds } 1144*1da177e4SLinus Torvalds 1145*1da177e4SLinus Torvalds static struct file_operations lec_seq_fops = { 1146*1da177e4SLinus Torvalds .owner = THIS_MODULE, 1147*1da177e4SLinus Torvalds .open = lec_seq_open, 1148*1da177e4SLinus Torvalds .read = seq_read, 1149*1da177e4SLinus Torvalds .llseek = seq_lseek, 1150*1da177e4SLinus Torvalds .release = lec_seq_release, 1151*1da177e4SLinus Torvalds }; 1152*1da177e4SLinus Torvalds #endif 1153*1da177e4SLinus Torvalds 1154*1da177e4SLinus Torvalds static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 1155*1da177e4SLinus Torvalds { 1156*1da177e4SLinus Torvalds struct atm_vcc *vcc = ATM_SD(sock); 1157*1da177e4SLinus Torvalds int err = 0; 1158*1da177e4SLinus Torvalds 1159*1da177e4SLinus Torvalds switch (cmd) { 1160*1da177e4SLinus Torvalds case ATMLEC_CTRL: 1161*1da177e4SLinus Torvalds case ATMLEC_MCAST: 1162*1da177e4SLinus Torvalds case ATMLEC_DATA: 1163*1da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN)) 1164*1da177e4SLinus Torvalds return -EPERM; 1165*1da177e4SLinus Torvalds break; 1166*1da177e4SLinus Torvalds default: 1167*1da177e4SLinus Torvalds return -ENOIOCTLCMD; 1168*1da177e4SLinus Torvalds } 1169*1da177e4SLinus Torvalds 1170*1da177e4SLinus Torvalds switch (cmd) { 1171*1da177e4SLinus Torvalds case ATMLEC_CTRL: 1172*1da177e4SLinus Torvalds err = lecd_attach(vcc, (int) arg); 1173*1da177e4SLinus Torvalds if (err >= 0) 1174*1da177e4SLinus Torvalds sock->state = SS_CONNECTED; 1175*1da177e4SLinus Torvalds break; 1176*1da177e4SLinus Torvalds case ATMLEC_MCAST: 1177*1da177e4SLinus Torvalds err = lec_mcast_attach(vcc, (int) arg); 1178*1da177e4SLinus Torvalds break; 1179*1da177e4SLinus Torvalds case ATMLEC_DATA: 1180*1da177e4SLinus Torvalds err = lec_vcc_attach(vcc, (void __user *) arg); 1181*1da177e4SLinus Torvalds break; 1182*1da177e4SLinus Torvalds } 1183*1da177e4SLinus Torvalds 1184*1da177e4SLinus Torvalds return err; 1185*1da177e4SLinus Torvalds } 1186*1da177e4SLinus Torvalds 1187*1da177e4SLinus Torvalds static struct atm_ioctl lane_ioctl_ops = { 1188*1da177e4SLinus Torvalds .owner = THIS_MODULE, 1189*1da177e4SLinus Torvalds .ioctl = lane_ioctl, 1190*1da177e4SLinus Torvalds }; 1191*1da177e4SLinus Torvalds 1192*1da177e4SLinus Torvalds static int __init lane_module_init(void) 1193*1da177e4SLinus Torvalds { 1194*1da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 1195*1da177e4SLinus Torvalds struct proc_dir_entry *p; 1196*1da177e4SLinus Torvalds 1197*1da177e4SLinus Torvalds p = create_proc_entry("lec", S_IRUGO, atm_proc_root); 1198*1da177e4SLinus Torvalds if (p) 1199*1da177e4SLinus Torvalds p->proc_fops = &lec_seq_fops; 1200*1da177e4SLinus Torvalds #endif 1201*1da177e4SLinus Torvalds 1202*1da177e4SLinus Torvalds register_atm_ioctl(&lane_ioctl_ops); 1203*1da177e4SLinus Torvalds printk("lec.c: " __DATE__ " " __TIME__ " initialized\n"); 1204*1da177e4SLinus Torvalds return 0; 1205*1da177e4SLinus Torvalds } 1206*1da177e4SLinus Torvalds 1207*1da177e4SLinus Torvalds static void __exit lane_module_cleanup(void) 1208*1da177e4SLinus Torvalds { 1209*1da177e4SLinus Torvalds int i; 1210*1da177e4SLinus Torvalds struct lec_priv *priv; 1211*1da177e4SLinus Torvalds 1212*1da177e4SLinus Torvalds remove_proc_entry("lec", atm_proc_root); 1213*1da177e4SLinus Torvalds 1214*1da177e4SLinus Torvalds deregister_atm_ioctl(&lane_ioctl_ops); 1215*1da177e4SLinus Torvalds 1216*1da177e4SLinus Torvalds for (i = 0; i < MAX_LEC_ITF; i++) { 1217*1da177e4SLinus Torvalds if (dev_lec[i] != NULL) { 1218*1da177e4SLinus Torvalds priv = (struct lec_priv *)dev_lec[i]->priv; 1219*1da177e4SLinus Torvalds unregister_netdev(dev_lec[i]); 1220*1da177e4SLinus Torvalds free_netdev(dev_lec[i]); 1221*1da177e4SLinus Torvalds dev_lec[i] = NULL; 1222*1da177e4SLinus Torvalds } 1223*1da177e4SLinus Torvalds } 1224*1da177e4SLinus Torvalds 1225*1da177e4SLinus Torvalds return; 1226*1da177e4SLinus Torvalds } 1227*1da177e4SLinus Torvalds 1228*1da177e4SLinus Torvalds module_init(lane_module_init); 1229*1da177e4SLinus Torvalds module_exit(lane_module_cleanup); 1230*1da177e4SLinus Torvalds 1231*1da177e4SLinus Torvalds /* 1232*1da177e4SLinus Torvalds * LANE2: 3.1.3, LE_RESOLVE.request 1233*1da177e4SLinus Torvalds * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs. 1234*1da177e4SLinus Torvalds * If sizeoftlvs == NULL the default TLVs associated with with this 1235*1da177e4SLinus Torvalds * lec will be used. 1236*1da177e4SLinus Torvalds * If dst_mac == NULL, targetless LE_ARP will be sent 1237*1da177e4SLinus Torvalds */ 1238*1da177e4SLinus Torvalds static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force, 1239*1da177e4SLinus Torvalds u8 **tlvs, u32 *sizeoftlvs) 1240*1da177e4SLinus Torvalds { 1241*1da177e4SLinus Torvalds unsigned long flags; 1242*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)dev->priv; 1243*1da177e4SLinus Torvalds struct lec_arp_table *table; 1244*1da177e4SLinus Torvalds struct sk_buff *skb; 1245*1da177e4SLinus Torvalds int retval; 1246*1da177e4SLinus Torvalds 1247*1da177e4SLinus Torvalds if (force == 0) { 1248*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 1249*1da177e4SLinus Torvalds table = lec_arp_find(priv, dst_mac); 1250*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 1251*1da177e4SLinus Torvalds if(table == NULL) 1252*1da177e4SLinus Torvalds return -1; 1253*1da177e4SLinus Torvalds 1254*1da177e4SLinus Torvalds *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC); 1255*1da177e4SLinus Torvalds if (*tlvs == NULL) 1256*1da177e4SLinus Torvalds return -1; 1257*1da177e4SLinus Torvalds 1258*1da177e4SLinus Torvalds memcpy(*tlvs, table->tlvs, table->sizeoftlvs); 1259*1da177e4SLinus Torvalds *sizeoftlvs = table->sizeoftlvs; 1260*1da177e4SLinus Torvalds 1261*1da177e4SLinus Torvalds return 0; 1262*1da177e4SLinus Torvalds } 1263*1da177e4SLinus Torvalds 1264*1da177e4SLinus Torvalds if (sizeoftlvs == NULL) 1265*1da177e4SLinus Torvalds retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL); 1266*1da177e4SLinus Torvalds 1267*1da177e4SLinus Torvalds else { 1268*1da177e4SLinus Torvalds skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC); 1269*1da177e4SLinus Torvalds if (skb == NULL) 1270*1da177e4SLinus Torvalds return -1; 1271*1da177e4SLinus Torvalds skb->len = *sizeoftlvs; 1272*1da177e4SLinus Torvalds memcpy(skb->data, *tlvs, *sizeoftlvs); 1273*1da177e4SLinus Torvalds retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb); 1274*1da177e4SLinus Torvalds } 1275*1da177e4SLinus Torvalds return retval; 1276*1da177e4SLinus Torvalds } 1277*1da177e4SLinus Torvalds 1278*1da177e4SLinus Torvalds 1279*1da177e4SLinus Torvalds /* 1280*1da177e4SLinus Torvalds * LANE2: 3.1.4, LE_ASSOCIATE.request 1281*1da177e4SLinus Torvalds * Associate the *tlvs with the *lan_dst address. 1282*1da177e4SLinus Torvalds * Will overwrite any previous association 1283*1da177e4SLinus Torvalds * Returns 1 for success, 0 for failure (out of memory) 1284*1da177e4SLinus Torvalds * 1285*1da177e4SLinus Torvalds */ 1286*1da177e4SLinus Torvalds static int lane2_associate_req (struct net_device *dev, u8 *lan_dst, 1287*1da177e4SLinus Torvalds u8 *tlvs, u32 sizeoftlvs) 1288*1da177e4SLinus Torvalds { 1289*1da177e4SLinus Torvalds int retval; 1290*1da177e4SLinus Torvalds struct sk_buff *skb; 1291*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv*)dev->priv; 1292*1da177e4SLinus Torvalds 1293*1da177e4SLinus Torvalds if ( memcmp(lan_dst, dev->dev_addr, ETH_ALEN) != 0 ) 1294*1da177e4SLinus Torvalds return (0); /* not our mac address */ 1295*1da177e4SLinus Torvalds 1296*1da177e4SLinus Torvalds kfree(priv->tlvs); /* NULL if there was no previous association */ 1297*1da177e4SLinus Torvalds 1298*1da177e4SLinus Torvalds priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); 1299*1da177e4SLinus Torvalds if (priv->tlvs == NULL) 1300*1da177e4SLinus Torvalds return (0); 1301*1da177e4SLinus Torvalds priv->sizeoftlvs = sizeoftlvs; 1302*1da177e4SLinus Torvalds memcpy(priv->tlvs, tlvs, sizeoftlvs); 1303*1da177e4SLinus Torvalds 1304*1da177e4SLinus Torvalds skb = alloc_skb(sizeoftlvs, GFP_ATOMIC); 1305*1da177e4SLinus Torvalds if (skb == NULL) 1306*1da177e4SLinus Torvalds return 0; 1307*1da177e4SLinus Torvalds skb->len = sizeoftlvs; 1308*1da177e4SLinus Torvalds memcpy(skb->data, tlvs, sizeoftlvs); 1309*1da177e4SLinus Torvalds retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb); 1310*1da177e4SLinus Torvalds if (retval != 0) 1311*1da177e4SLinus Torvalds printk("lec.c: lane2_associate_req() failed\n"); 1312*1da177e4SLinus Torvalds /* If the previous association has changed we must 1313*1da177e4SLinus Torvalds * somehow notify other LANE entities about the change 1314*1da177e4SLinus Torvalds */ 1315*1da177e4SLinus Torvalds return (1); 1316*1da177e4SLinus Torvalds } 1317*1da177e4SLinus Torvalds 1318*1da177e4SLinus Torvalds /* 1319*1da177e4SLinus Torvalds * LANE2: 3.1.5, LE_ASSOCIATE.indication 1320*1da177e4SLinus Torvalds * 1321*1da177e4SLinus Torvalds */ 1322*1da177e4SLinus Torvalds static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr, 1323*1da177e4SLinus Torvalds u8 *tlvs, u32 sizeoftlvs) 1324*1da177e4SLinus Torvalds { 1325*1da177e4SLinus Torvalds #if 0 1326*1da177e4SLinus Torvalds int i = 0; 1327*1da177e4SLinus Torvalds #endif 1328*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)dev->priv; 1329*1da177e4SLinus Torvalds #if 0 /* Why have the TLVs in LE_ARP entries since we do not use them? When you 1330*1da177e4SLinus Torvalds uncomment this code, make sure the TLVs get freed when entry is killed */ 1331*1da177e4SLinus Torvalds struct lec_arp_table *entry = lec_arp_find(priv, mac_addr); 1332*1da177e4SLinus Torvalds 1333*1da177e4SLinus Torvalds if (entry == NULL) 1334*1da177e4SLinus Torvalds return; /* should not happen */ 1335*1da177e4SLinus Torvalds 1336*1da177e4SLinus Torvalds kfree(entry->tlvs); 1337*1da177e4SLinus Torvalds 1338*1da177e4SLinus Torvalds entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); 1339*1da177e4SLinus Torvalds if (entry->tlvs == NULL) 1340*1da177e4SLinus Torvalds return; 1341*1da177e4SLinus Torvalds 1342*1da177e4SLinus Torvalds entry->sizeoftlvs = sizeoftlvs; 1343*1da177e4SLinus Torvalds memcpy(entry->tlvs, tlvs, sizeoftlvs); 1344*1da177e4SLinus Torvalds #endif 1345*1da177e4SLinus Torvalds #if 0 1346*1da177e4SLinus Torvalds printk("lec.c: lane2_associate_ind()\n"); 1347*1da177e4SLinus Torvalds printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs); 1348*1da177e4SLinus Torvalds while (i < sizeoftlvs) 1349*1da177e4SLinus Torvalds printk("%02x ", tlvs[i++]); 1350*1da177e4SLinus Torvalds 1351*1da177e4SLinus Torvalds printk("\n"); 1352*1da177e4SLinus Torvalds #endif 1353*1da177e4SLinus Torvalds 1354*1da177e4SLinus Torvalds /* tell MPOA about the TLVs we saw */ 1355*1da177e4SLinus Torvalds if (priv->lane2_ops && priv->lane2_ops->associate_indicator) { 1356*1da177e4SLinus Torvalds priv->lane2_ops->associate_indicator(dev, mac_addr, 1357*1da177e4SLinus Torvalds tlvs, sizeoftlvs); 1358*1da177e4SLinus Torvalds } 1359*1da177e4SLinus Torvalds return; 1360*1da177e4SLinus Torvalds } 1361*1da177e4SLinus Torvalds 1362*1da177e4SLinus Torvalds /* 1363*1da177e4SLinus Torvalds * Here starts what used to lec_arpc.c 1364*1da177e4SLinus Torvalds * 1365*1da177e4SLinus Torvalds * lec_arpc.c was added here when making 1366*1da177e4SLinus Torvalds * lane client modular. October 1997 1367*1da177e4SLinus Torvalds * 1368*1da177e4SLinus Torvalds */ 1369*1da177e4SLinus Torvalds 1370*1da177e4SLinus Torvalds #include <linux/types.h> 1371*1da177e4SLinus Torvalds #include <linux/sched.h> 1372*1da177e4SLinus Torvalds #include <linux/timer.h> 1373*1da177e4SLinus Torvalds #include <asm/param.h> 1374*1da177e4SLinus Torvalds #include <asm/atomic.h> 1375*1da177e4SLinus Torvalds #include <linux/inetdevice.h> 1376*1da177e4SLinus Torvalds #include <net/route.h> 1377*1da177e4SLinus Torvalds 1378*1da177e4SLinus Torvalds 1379*1da177e4SLinus Torvalds #if 0 1380*1da177e4SLinus Torvalds #define DPRINTK(format,args...) 1381*1da177e4SLinus Torvalds /* 1382*1da177e4SLinus Torvalds #define DPRINTK printk 1383*1da177e4SLinus Torvalds */ 1384*1da177e4SLinus Torvalds #endif 1385*1da177e4SLinus Torvalds #define DEBUG_ARP_TABLE 0 1386*1da177e4SLinus Torvalds 1387*1da177e4SLinus Torvalds #define LEC_ARP_REFRESH_INTERVAL (3*HZ) 1388*1da177e4SLinus Torvalds 1389*1da177e4SLinus Torvalds static void lec_arp_check_expire(unsigned long data); 1390*1da177e4SLinus Torvalds static void lec_arp_expire_arp(unsigned long data); 1391*1da177e4SLinus Torvalds 1392*1da177e4SLinus Torvalds /* 1393*1da177e4SLinus Torvalds * Arp table funcs 1394*1da177e4SLinus Torvalds */ 1395*1da177e4SLinus Torvalds 1396*1da177e4SLinus Torvalds #define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1)) 1397*1da177e4SLinus Torvalds 1398*1da177e4SLinus Torvalds /* 1399*1da177e4SLinus Torvalds * Initialization of arp-cache 1400*1da177e4SLinus Torvalds */ 1401*1da177e4SLinus Torvalds static void 1402*1da177e4SLinus Torvalds lec_arp_init(struct lec_priv *priv) 1403*1da177e4SLinus Torvalds { 1404*1da177e4SLinus Torvalds unsigned short i; 1405*1da177e4SLinus Torvalds 1406*1da177e4SLinus Torvalds for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 1407*1da177e4SLinus Torvalds priv->lec_arp_tables[i] = NULL; 1408*1da177e4SLinus Torvalds } 1409*1da177e4SLinus Torvalds spin_lock_init(&priv->lec_arp_lock); 1410*1da177e4SLinus Torvalds init_timer(&priv->lec_arp_timer); 1411*1da177e4SLinus Torvalds priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; 1412*1da177e4SLinus Torvalds priv->lec_arp_timer.data = (unsigned long)priv; 1413*1da177e4SLinus Torvalds priv->lec_arp_timer.function = lec_arp_check_expire; 1414*1da177e4SLinus Torvalds add_timer(&priv->lec_arp_timer); 1415*1da177e4SLinus Torvalds } 1416*1da177e4SLinus Torvalds 1417*1da177e4SLinus Torvalds static void 1418*1da177e4SLinus Torvalds lec_arp_clear_vccs(struct lec_arp_table *entry) 1419*1da177e4SLinus Torvalds { 1420*1da177e4SLinus Torvalds if (entry->vcc) { 1421*1da177e4SLinus Torvalds struct atm_vcc *vcc = entry->vcc; 1422*1da177e4SLinus Torvalds struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); 1423*1da177e4SLinus Torvalds struct net_device *dev = (struct net_device*) vcc->proto_data; 1424*1da177e4SLinus Torvalds 1425*1da177e4SLinus Torvalds vcc->pop = vpriv->old_pop; 1426*1da177e4SLinus Torvalds if (vpriv->xoff) 1427*1da177e4SLinus Torvalds netif_wake_queue(dev); 1428*1da177e4SLinus Torvalds kfree(vpriv); 1429*1da177e4SLinus Torvalds vcc->user_back = NULL; 1430*1da177e4SLinus Torvalds vcc->push = entry->old_push; 1431*1da177e4SLinus Torvalds vcc_release_async(vcc, -EPIPE); 1432*1da177e4SLinus Torvalds vcc = NULL; 1433*1da177e4SLinus Torvalds } 1434*1da177e4SLinus Torvalds if (entry->recv_vcc) { 1435*1da177e4SLinus Torvalds entry->recv_vcc->push = entry->old_recv_push; 1436*1da177e4SLinus Torvalds vcc_release_async(entry->recv_vcc, -EPIPE); 1437*1da177e4SLinus Torvalds entry->recv_vcc = NULL; 1438*1da177e4SLinus Torvalds } 1439*1da177e4SLinus Torvalds } 1440*1da177e4SLinus Torvalds 1441*1da177e4SLinus Torvalds /* 1442*1da177e4SLinus Torvalds * Insert entry to lec_arp_table 1443*1da177e4SLinus Torvalds * LANE2: Add to the end of the list to satisfy 8.1.13 1444*1da177e4SLinus Torvalds */ 1445*1da177e4SLinus Torvalds static inline void 1446*1da177e4SLinus Torvalds lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) 1447*1da177e4SLinus Torvalds { 1448*1da177e4SLinus Torvalds unsigned short place; 1449*1da177e4SLinus Torvalds struct lec_arp_table *tmp; 1450*1da177e4SLinus Torvalds 1451*1da177e4SLinus Torvalds place = HASH(to_add->mac_addr[ETH_ALEN-1]); 1452*1da177e4SLinus Torvalds tmp = priv->lec_arp_tables[place]; 1453*1da177e4SLinus Torvalds to_add->next = NULL; 1454*1da177e4SLinus Torvalds if (tmp == NULL) 1455*1da177e4SLinus Torvalds priv->lec_arp_tables[place] = to_add; 1456*1da177e4SLinus Torvalds 1457*1da177e4SLinus Torvalds else { /* add to the end */ 1458*1da177e4SLinus Torvalds while (tmp->next) 1459*1da177e4SLinus Torvalds tmp = tmp->next; 1460*1da177e4SLinus Torvalds tmp->next = to_add; 1461*1da177e4SLinus Torvalds } 1462*1da177e4SLinus Torvalds 1463*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 1464*1da177e4SLinus Torvalds 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1], 1465*1da177e4SLinus Torvalds 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3], 1466*1da177e4SLinus Torvalds 0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]); 1467*1da177e4SLinus Torvalds } 1468*1da177e4SLinus Torvalds 1469*1da177e4SLinus Torvalds /* 1470*1da177e4SLinus Torvalds * Remove entry from lec_arp_table 1471*1da177e4SLinus Torvalds */ 1472*1da177e4SLinus Torvalds static int 1473*1da177e4SLinus Torvalds lec_arp_remove(struct lec_priv *priv, 1474*1da177e4SLinus Torvalds struct lec_arp_table *to_remove) 1475*1da177e4SLinus Torvalds { 1476*1da177e4SLinus Torvalds unsigned short place; 1477*1da177e4SLinus Torvalds struct lec_arp_table *tmp; 1478*1da177e4SLinus Torvalds int remove_vcc=1; 1479*1da177e4SLinus Torvalds 1480*1da177e4SLinus Torvalds if (!to_remove) { 1481*1da177e4SLinus Torvalds return -1; 1482*1da177e4SLinus Torvalds } 1483*1da177e4SLinus Torvalds place = HASH(to_remove->mac_addr[ETH_ALEN-1]); 1484*1da177e4SLinus Torvalds tmp = priv->lec_arp_tables[place]; 1485*1da177e4SLinus Torvalds if (tmp == to_remove) { 1486*1da177e4SLinus Torvalds priv->lec_arp_tables[place] = tmp->next; 1487*1da177e4SLinus Torvalds } else { 1488*1da177e4SLinus Torvalds while(tmp && tmp->next != to_remove) { 1489*1da177e4SLinus Torvalds tmp = tmp->next; 1490*1da177e4SLinus Torvalds } 1491*1da177e4SLinus Torvalds if (!tmp) {/* Entry was not found */ 1492*1da177e4SLinus Torvalds return -1; 1493*1da177e4SLinus Torvalds } 1494*1da177e4SLinus Torvalds } 1495*1da177e4SLinus Torvalds tmp->next = to_remove->next; 1496*1da177e4SLinus Torvalds del_timer(&to_remove->timer); 1497*1da177e4SLinus Torvalds 1498*1da177e4SLinus Torvalds /* If this is the only MAC connected to this VCC, also tear down 1499*1da177e4SLinus Torvalds the VCC */ 1500*1da177e4SLinus Torvalds if (to_remove->status >= ESI_FLUSH_PENDING) { 1501*1da177e4SLinus Torvalds /* 1502*1da177e4SLinus Torvalds * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT 1503*1da177e4SLinus Torvalds */ 1504*1da177e4SLinus Torvalds for(place = 0; place < LEC_ARP_TABLE_SIZE; place++) { 1505*1da177e4SLinus Torvalds for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) { 1506*1da177e4SLinus Torvalds if (memcmp(tmp->atm_addr, to_remove->atm_addr, 1507*1da177e4SLinus Torvalds ATM_ESA_LEN)==0) { 1508*1da177e4SLinus Torvalds remove_vcc=0; 1509*1da177e4SLinus Torvalds break; 1510*1da177e4SLinus Torvalds } 1511*1da177e4SLinus Torvalds } 1512*1da177e4SLinus Torvalds } 1513*1da177e4SLinus Torvalds if (remove_vcc) 1514*1da177e4SLinus Torvalds lec_arp_clear_vccs(to_remove); 1515*1da177e4SLinus Torvalds } 1516*1da177e4SLinus Torvalds skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */ 1517*1da177e4SLinus Torvalds 1518*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 1519*1da177e4SLinus Torvalds 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1], 1520*1da177e4SLinus Torvalds 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3], 1521*1da177e4SLinus Torvalds 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]); 1522*1da177e4SLinus Torvalds return 0; 1523*1da177e4SLinus Torvalds } 1524*1da177e4SLinus Torvalds 1525*1da177e4SLinus Torvalds #if DEBUG_ARP_TABLE 1526*1da177e4SLinus Torvalds static char* 1527*1da177e4SLinus Torvalds get_status_string(unsigned char st) 1528*1da177e4SLinus Torvalds { 1529*1da177e4SLinus Torvalds switch(st) { 1530*1da177e4SLinus Torvalds case ESI_UNKNOWN: 1531*1da177e4SLinus Torvalds return "ESI_UNKNOWN"; 1532*1da177e4SLinus Torvalds case ESI_ARP_PENDING: 1533*1da177e4SLinus Torvalds return "ESI_ARP_PENDING"; 1534*1da177e4SLinus Torvalds case ESI_VC_PENDING: 1535*1da177e4SLinus Torvalds return "ESI_VC_PENDING"; 1536*1da177e4SLinus Torvalds case ESI_FLUSH_PENDING: 1537*1da177e4SLinus Torvalds return "ESI_FLUSH_PENDING"; 1538*1da177e4SLinus Torvalds case ESI_FORWARD_DIRECT: 1539*1da177e4SLinus Torvalds return "ESI_FORWARD_DIRECT"; 1540*1da177e4SLinus Torvalds default: 1541*1da177e4SLinus Torvalds return "<UNKNOWN>"; 1542*1da177e4SLinus Torvalds } 1543*1da177e4SLinus Torvalds } 1544*1da177e4SLinus Torvalds #endif 1545*1da177e4SLinus Torvalds 1546*1da177e4SLinus Torvalds static void 1547*1da177e4SLinus Torvalds dump_arp_table(struct lec_priv *priv) 1548*1da177e4SLinus Torvalds { 1549*1da177e4SLinus Torvalds #if DEBUG_ARP_TABLE 1550*1da177e4SLinus Torvalds int i,j, offset; 1551*1da177e4SLinus Torvalds struct lec_arp_table *rulla; 1552*1da177e4SLinus Torvalds char buf[1024]; 1553*1da177e4SLinus Torvalds struct lec_arp_table **lec_arp_tables = 1554*1da177e4SLinus Torvalds (struct lec_arp_table **)priv->lec_arp_tables; 1555*1da177e4SLinus Torvalds struct lec_arp_table *lec_arp_empty_ones = 1556*1da177e4SLinus Torvalds (struct lec_arp_table *)priv->lec_arp_empty_ones; 1557*1da177e4SLinus Torvalds struct lec_arp_table *lec_no_forward = 1558*1da177e4SLinus Torvalds (struct lec_arp_table *)priv->lec_no_forward; 1559*1da177e4SLinus Torvalds struct lec_arp_table *mcast_fwds = priv->mcast_fwds; 1560*1da177e4SLinus Torvalds 1561*1da177e4SLinus Torvalds 1562*1da177e4SLinus Torvalds printk("Dump %p:\n",priv); 1563*1da177e4SLinus Torvalds for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { 1564*1da177e4SLinus Torvalds rulla = lec_arp_tables[i]; 1565*1da177e4SLinus Torvalds offset = 0; 1566*1da177e4SLinus Torvalds offset += sprintf(buf,"%d: %p\n",i, rulla); 1567*1da177e4SLinus Torvalds while (rulla) { 1568*1da177e4SLinus Torvalds offset += sprintf(buf+offset,"Mac:"); 1569*1da177e4SLinus Torvalds for(j=0;j<ETH_ALEN;j++) { 1570*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1571*1da177e4SLinus Torvalds "%2.2x ", 1572*1da177e4SLinus Torvalds rulla->mac_addr[j]&0xff); 1573*1da177e4SLinus Torvalds } 1574*1da177e4SLinus Torvalds offset +=sprintf(buf+offset,"Atm:"); 1575*1da177e4SLinus Torvalds for(j=0;j<ATM_ESA_LEN;j++) { 1576*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1577*1da177e4SLinus Torvalds "%2.2x ", 1578*1da177e4SLinus Torvalds rulla->atm_addr[j]&0xff); 1579*1da177e4SLinus Torvalds } 1580*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1581*1da177e4SLinus Torvalds "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", 1582*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vpi:0, 1583*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vci:0, 1584*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vpi:0, 1585*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vci:0, 1586*1da177e4SLinus Torvalds rulla->last_used, 1587*1da177e4SLinus Torvalds rulla->timestamp, rulla->no_tries); 1588*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1589*1da177e4SLinus Torvalds "Flags:%x, Packets_flooded:%x, Status: %s ", 1590*1da177e4SLinus Torvalds rulla->flags, rulla->packets_flooded, 1591*1da177e4SLinus Torvalds get_status_string(rulla->status)); 1592*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"->%p\n",rulla->next); 1593*1da177e4SLinus Torvalds rulla = rulla->next; 1594*1da177e4SLinus Torvalds } 1595*1da177e4SLinus Torvalds printk("%s",buf); 1596*1da177e4SLinus Torvalds } 1597*1da177e4SLinus Torvalds rulla = lec_no_forward; 1598*1da177e4SLinus Torvalds if (rulla) 1599*1da177e4SLinus Torvalds printk("No forward\n"); 1600*1da177e4SLinus Torvalds while(rulla) { 1601*1da177e4SLinus Torvalds offset=0; 1602*1da177e4SLinus Torvalds offset += sprintf(buf+offset,"Mac:"); 1603*1da177e4SLinus Torvalds for(j=0;j<ETH_ALEN;j++) { 1604*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"%2.2x ", 1605*1da177e4SLinus Torvalds rulla->mac_addr[j]&0xff); 1606*1da177e4SLinus Torvalds } 1607*1da177e4SLinus Torvalds offset +=sprintf(buf+offset,"Atm:"); 1608*1da177e4SLinus Torvalds for(j=0;j<ATM_ESA_LEN;j++) { 1609*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"%2.2x ", 1610*1da177e4SLinus Torvalds rulla->atm_addr[j]&0xff); 1611*1da177e4SLinus Torvalds } 1612*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1613*1da177e4SLinus Torvalds "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", 1614*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vpi:0, 1615*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vci:0, 1616*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vpi:0, 1617*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vci:0, 1618*1da177e4SLinus Torvalds rulla->last_used, 1619*1da177e4SLinus Torvalds rulla->timestamp, rulla->no_tries); 1620*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1621*1da177e4SLinus Torvalds "Flags:%x, Packets_flooded:%x, Status: %s ", 1622*1da177e4SLinus Torvalds rulla->flags, rulla->packets_flooded, 1623*1da177e4SLinus Torvalds get_status_string(rulla->status)); 1624*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); 1625*1da177e4SLinus Torvalds rulla = rulla->next; 1626*1da177e4SLinus Torvalds printk("%s",buf); 1627*1da177e4SLinus Torvalds } 1628*1da177e4SLinus Torvalds rulla = lec_arp_empty_ones; 1629*1da177e4SLinus Torvalds if (rulla) 1630*1da177e4SLinus Torvalds printk("Empty ones\n"); 1631*1da177e4SLinus Torvalds while(rulla) { 1632*1da177e4SLinus Torvalds offset=0; 1633*1da177e4SLinus Torvalds offset += sprintf(buf+offset,"Mac:"); 1634*1da177e4SLinus Torvalds for(j=0;j<ETH_ALEN;j++) { 1635*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"%2.2x ", 1636*1da177e4SLinus Torvalds rulla->mac_addr[j]&0xff); 1637*1da177e4SLinus Torvalds } 1638*1da177e4SLinus Torvalds offset +=sprintf(buf+offset,"Atm:"); 1639*1da177e4SLinus Torvalds for(j=0;j<ATM_ESA_LEN;j++) { 1640*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"%2.2x ", 1641*1da177e4SLinus Torvalds rulla->atm_addr[j]&0xff); 1642*1da177e4SLinus Torvalds } 1643*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1644*1da177e4SLinus Torvalds "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", 1645*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vpi:0, 1646*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vci:0, 1647*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vpi:0, 1648*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vci:0, 1649*1da177e4SLinus Torvalds rulla->last_used, 1650*1da177e4SLinus Torvalds rulla->timestamp, rulla->no_tries); 1651*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1652*1da177e4SLinus Torvalds "Flags:%x, Packets_flooded:%x, Status: %s ", 1653*1da177e4SLinus Torvalds rulla->flags, rulla->packets_flooded, 1654*1da177e4SLinus Torvalds get_status_string(rulla->status)); 1655*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); 1656*1da177e4SLinus Torvalds rulla = rulla->next; 1657*1da177e4SLinus Torvalds printk("%s",buf); 1658*1da177e4SLinus Torvalds } 1659*1da177e4SLinus Torvalds 1660*1da177e4SLinus Torvalds rulla = mcast_fwds; 1661*1da177e4SLinus Torvalds if (rulla) 1662*1da177e4SLinus Torvalds printk("Multicast Forward VCCs\n"); 1663*1da177e4SLinus Torvalds while(rulla) { 1664*1da177e4SLinus Torvalds offset=0; 1665*1da177e4SLinus Torvalds offset += sprintf(buf+offset,"Mac:"); 1666*1da177e4SLinus Torvalds for(j=0;j<ETH_ALEN;j++) { 1667*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"%2.2x ", 1668*1da177e4SLinus Torvalds rulla->mac_addr[j]&0xff); 1669*1da177e4SLinus Torvalds } 1670*1da177e4SLinus Torvalds offset +=sprintf(buf+offset,"Atm:"); 1671*1da177e4SLinus Torvalds for(j=0;j<ATM_ESA_LEN;j++) { 1672*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"%2.2x ", 1673*1da177e4SLinus Torvalds rulla->atm_addr[j]&0xff); 1674*1da177e4SLinus Torvalds } 1675*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1676*1da177e4SLinus Torvalds "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", 1677*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vpi:0, 1678*1da177e4SLinus Torvalds rulla->vcc?rulla->vcc->vci:0, 1679*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vpi:0, 1680*1da177e4SLinus Torvalds rulla->recv_vcc?rulla->recv_vcc->vci:0, 1681*1da177e4SLinus Torvalds rulla->last_used, 1682*1da177e4SLinus Torvalds rulla->timestamp, rulla->no_tries); 1683*1da177e4SLinus Torvalds offset+=sprintf(buf+offset, 1684*1da177e4SLinus Torvalds "Flags:%x, Packets_flooded:%x, Status: %s ", 1685*1da177e4SLinus Torvalds rulla->flags, rulla->packets_flooded, 1686*1da177e4SLinus Torvalds get_status_string(rulla->status)); 1687*1da177e4SLinus Torvalds offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); 1688*1da177e4SLinus Torvalds rulla = rulla->next; 1689*1da177e4SLinus Torvalds printk("%s",buf); 1690*1da177e4SLinus Torvalds } 1691*1da177e4SLinus Torvalds 1692*1da177e4SLinus Torvalds #endif 1693*1da177e4SLinus Torvalds } 1694*1da177e4SLinus Torvalds 1695*1da177e4SLinus Torvalds /* 1696*1da177e4SLinus Torvalds * Destruction of arp-cache 1697*1da177e4SLinus Torvalds */ 1698*1da177e4SLinus Torvalds static void 1699*1da177e4SLinus Torvalds lec_arp_destroy(struct lec_priv *priv) 1700*1da177e4SLinus Torvalds { 1701*1da177e4SLinus Torvalds unsigned long flags; 1702*1da177e4SLinus Torvalds struct lec_arp_table *entry, *next; 1703*1da177e4SLinus Torvalds int i; 1704*1da177e4SLinus Torvalds 1705*1da177e4SLinus Torvalds del_timer_sync(&priv->lec_arp_timer); 1706*1da177e4SLinus Torvalds 1707*1da177e4SLinus Torvalds /* 1708*1da177e4SLinus Torvalds * Remove all entries 1709*1da177e4SLinus Torvalds */ 1710*1da177e4SLinus Torvalds 1711*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 1712*1da177e4SLinus Torvalds for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 1713*1da177e4SLinus Torvalds for(entry = priv->lec_arp_tables[i]; entry != NULL; entry=next) { 1714*1da177e4SLinus Torvalds next = entry->next; 1715*1da177e4SLinus Torvalds lec_arp_remove(priv, entry); 1716*1da177e4SLinus Torvalds kfree(entry); 1717*1da177e4SLinus Torvalds } 1718*1da177e4SLinus Torvalds } 1719*1da177e4SLinus Torvalds entry = priv->lec_arp_empty_ones; 1720*1da177e4SLinus Torvalds while(entry) { 1721*1da177e4SLinus Torvalds next = entry->next; 1722*1da177e4SLinus Torvalds del_timer_sync(&entry->timer); 1723*1da177e4SLinus Torvalds lec_arp_clear_vccs(entry); 1724*1da177e4SLinus Torvalds kfree(entry); 1725*1da177e4SLinus Torvalds entry = next; 1726*1da177e4SLinus Torvalds } 1727*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = NULL; 1728*1da177e4SLinus Torvalds entry = priv->lec_no_forward; 1729*1da177e4SLinus Torvalds while(entry) { 1730*1da177e4SLinus Torvalds next = entry->next; 1731*1da177e4SLinus Torvalds del_timer_sync(&entry->timer); 1732*1da177e4SLinus Torvalds lec_arp_clear_vccs(entry); 1733*1da177e4SLinus Torvalds kfree(entry); 1734*1da177e4SLinus Torvalds entry = next; 1735*1da177e4SLinus Torvalds } 1736*1da177e4SLinus Torvalds priv->lec_no_forward = NULL; 1737*1da177e4SLinus Torvalds entry = priv->mcast_fwds; 1738*1da177e4SLinus Torvalds while(entry) { 1739*1da177e4SLinus Torvalds next = entry->next; 1740*1da177e4SLinus Torvalds /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ 1741*1da177e4SLinus Torvalds lec_arp_clear_vccs(entry); 1742*1da177e4SLinus Torvalds kfree(entry); 1743*1da177e4SLinus Torvalds entry = next; 1744*1da177e4SLinus Torvalds } 1745*1da177e4SLinus Torvalds priv->mcast_fwds = NULL; 1746*1da177e4SLinus Torvalds priv->mcast_vcc = NULL; 1747*1da177e4SLinus Torvalds memset(priv->lec_arp_tables, 0, 1748*1da177e4SLinus Torvalds sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE); 1749*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 1750*1da177e4SLinus Torvalds } 1751*1da177e4SLinus Torvalds 1752*1da177e4SLinus Torvalds 1753*1da177e4SLinus Torvalds /* 1754*1da177e4SLinus Torvalds * Find entry by mac_address 1755*1da177e4SLinus Torvalds */ 1756*1da177e4SLinus Torvalds static struct lec_arp_table* 1757*1da177e4SLinus Torvalds lec_arp_find(struct lec_priv *priv, 1758*1da177e4SLinus Torvalds unsigned char *mac_addr) 1759*1da177e4SLinus Torvalds { 1760*1da177e4SLinus Torvalds unsigned short place; 1761*1da177e4SLinus Torvalds struct lec_arp_table *to_return; 1762*1da177e4SLinus Torvalds 1763*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 1764*1da177e4SLinus Torvalds mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff, 1765*1da177e4SLinus Torvalds mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff); 1766*1da177e4SLinus Torvalds place = HASH(mac_addr[ETH_ALEN-1]); 1767*1da177e4SLinus Torvalds 1768*1da177e4SLinus Torvalds to_return = priv->lec_arp_tables[place]; 1769*1da177e4SLinus Torvalds while(to_return) { 1770*1da177e4SLinus Torvalds if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) { 1771*1da177e4SLinus Torvalds return to_return; 1772*1da177e4SLinus Torvalds } 1773*1da177e4SLinus Torvalds to_return = to_return->next; 1774*1da177e4SLinus Torvalds } 1775*1da177e4SLinus Torvalds return NULL; 1776*1da177e4SLinus Torvalds } 1777*1da177e4SLinus Torvalds 1778*1da177e4SLinus Torvalds static struct lec_arp_table* 1779*1da177e4SLinus Torvalds make_entry(struct lec_priv *priv, unsigned char *mac_addr) 1780*1da177e4SLinus Torvalds { 1781*1da177e4SLinus Torvalds struct lec_arp_table *to_return; 1782*1da177e4SLinus Torvalds 1783*1da177e4SLinus Torvalds to_return = (struct lec_arp_table *) kmalloc(sizeof(struct lec_arp_table), 1784*1da177e4SLinus Torvalds GFP_ATOMIC); 1785*1da177e4SLinus Torvalds if (!to_return) { 1786*1da177e4SLinus Torvalds printk("LEC: Arp entry kmalloc failed\n"); 1787*1da177e4SLinus Torvalds return NULL; 1788*1da177e4SLinus Torvalds } 1789*1da177e4SLinus Torvalds memset(to_return, 0, sizeof(struct lec_arp_table)); 1790*1da177e4SLinus Torvalds memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); 1791*1da177e4SLinus Torvalds init_timer(&to_return->timer); 1792*1da177e4SLinus Torvalds to_return->timer.function = lec_arp_expire_arp; 1793*1da177e4SLinus Torvalds to_return->timer.data = (unsigned long) to_return; 1794*1da177e4SLinus Torvalds to_return->last_used = jiffies; 1795*1da177e4SLinus Torvalds to_return->priv = priv; 1796*1da177e4SLinus Torvalds skb_queue_head_init(&to_return->tx_wait); 1797*1da177e4SLinus Torvalds return to_return; 1798*1da177e4SLinus Torvalds } 1799*1da177e4SLinus Torvalds 1800*1da177e4SLinus Torvalds /* 1801*1da177e4SLinus Torvalds * 1802*1da177e4SLinus Torvalds * Arp sent timer expired 1803*1da177e4SLinus Torvalds * 1804*1da177e4SLinus Torvalds */ 1805*1da177e4SLinus Torvalds static void 1806*1da177e4SLinus Torvalds lec_arp_expire_arp(unsigned long data) 1807*1da177e4SLinus Torvalds { 1808*1da177e4SLinus Torvalds struct lec_arp_table *entry; 1809*1da177e4SLinus Torvalds 1810*1da177e4SLinus Torvalds entry = (struct lec_arp_table *)data; 1811*1da177e4SLinus Torvalds 1812*1da177e4SLinus Torvalds DPRINTK("lec_arp_expire_arp\n"); 1813*1da177e4SLinus Torvalds if (entry->status == ESI_ARP_PENDING) { 1814*1da177e4SLinus Torvalds if (entry->no_tries <= entry->priv->max_retry_count) { 1815*1da177e4SLinus Torvalds if (entry->is_rdesc) 1816*1da177e4SLinus Torvalds send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL); 1817*1da177e4SLinus Torvalds else 1818*1da177e4SLinus Torvalds send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL); 1819*1da177e4SLinus Torvalds entry->no_tries++; 1820*1da177e4SLinus Torvalds } 1821*1da177e4SLinus Torvalds mod_timer(&entry->timer, jiffies + (1*HZ)); 1822*1da177e4SLinus Torvalds } 1823*1da177e4SLinus Torvalds } 1824*1da177e4SLinus Torvalds 1825*1da177e4SLinus Torvalds /* 1826*1da177e4SLinus Torvalds * 1827*1da177e4SLinus Torvalds * Unknown/unused vcc expire, remove associated entry 1828*1da177e4SLinus Torvalds * 1829*1da177e4SLinus Torvalds */ 1830*1da177e4SLinus Torvalds static void 1831*1da177e4SLinus Torvalds lec_arp_expire_vcc(unsigned long data) 1832*1da177e4SLinus Torvalds { 1833*1da177e4SLinus Torvalds unsigned long flags; 1834*1da177e4SLinus Torvalds struct lec_arp_table *to_remove = (struct lec_arp_table*)data; 1835*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)to_remove->priv; 1836*1da177e4SLinus Torvalds struct lec_arp_table *entry = NULL; 1837*1da177e4SLinus Torvalds 1838*1da177e4SLinus Torvalds del_timer(&to_remove->timer); 1839*1da177e4SLinus Torvalds 1840*1da177e4SLinus Torvalds DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n", 1841*1da177e4SLinus Torvalds to_remove, priv, 1842*1da177e4SLinus Torvalds to_remove->vcc?to_remove->recv_vcc->vpi:0, 1843*1da177e4SLinus Torvalds to_remove->vcc?to_remove->recv_vcc->vci:0); 1844*1da177e4SLinus Torvalds DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward); 1845*1da177e4SLinus Torvalds 1846*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 1847*1da177e4SLinus Torvalds if (to_remove == priv->lec_arp_empty_ones) 1848*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = to_remove->next; 1849*1da177e4SLinus Torvalds else { 1850*1da177e4SLinus Torvalds entry = priv->lec_arp_empty_ones; 1851*1da177e4SLinus Torvalds while (entry && entry->next != to_remove) 1852*1da177e4SLinus Torvalds entry = entry->next; 1853*1da177e4SLinus Torvalds if (entry) 1854*1da177e4SLinus Torvalds entry->next = to_remove->next; 1855*1da177e4SLinus Torvalds } 1856*1da177e4SLinus Torvalds if (!entry) { 1857*1da177e4SLinus Torvalds if (to_remove == priv->lec_no_forward) { 1858*1da177e4SLinus Torvalds priv->lec_no_forward = to_remove->next; 1859*1da177e4SLinus Torvalds } else { 1860*1da177e4SLinus Torvalds entry = priv->lec_no_forward; 1861*1da177e4SLinus Torvalds while (entry && entry->next != to_remove) 1862*1da177e4SLinus Torvalds entry = entry->next; 1863*1da177e4SLinus Torvalds if (entry) 1864*1da177e4SLinus Torvalds entry->next = to_remove->next; 1865*1da177e4SLinus Torvalds } 1866*1da177e4SLinus Torvalds } 1867*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 1868*1da177e4SLinus Torvalds 1869*1da177e4SLinus Torvalds lec_arp_clear_vccs(to_remove); 1870*1da177e4SLinus Torvalds kfree(to_remove); 1871*1da177e4SLinus Torvalds } 1872*1da177e4SLinus Torvalds 1873*1da177e4SLinus Torvalds /* 1874*1da177e4SLinus Torvalds * Expire entries. 1875*1da177e4SLinus Torvalds * 1. Re-set timer 1876*1da177e4SLinus Torvalds * 2. For each entry, delete entries that have aged past the age limit. 1877*1da177e4SLinus Torvalds * 3. For each entry, depending on the status of the entry, perform 1878*1da177e4SLinus Torvalds * the following maintenance. 1879*1da177e4SLinus Torvalds * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the 1880*1da177e4SLinus Torvalds * tick_count is above the max_unknown_frame_time, clear 1881*1da177e4SLinus Torvalds * the tick_count to zero and clear the packets_flooded counter 1882*1da177e4SLinus Torvalds * to zero. This supports the packet rate limit per address 1883*1da177e4SLinus Torvalds * while flooding unknowns. 1884*1da177e4SLinus Torvalds * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater 1885*1da177e4SLinus Torvalds * than or equal to the path_switching_delay, change the status 1886*1da177e4SLinus Torvalds * to ESI_FORWARD_DIRECT. This causes the flush period to end 1887*1da177e4SLinus Torvalds * regardless of the progress of the flush protocol. 1888*1da177e4SLinus Torvalds */ 1889*1da177e4SLinus Torvalds static void 1890*1da177e4SLinus Torvalds lec_arp_check_expire(unsigned long data) 1891*1da177e4SLinus Torvalds { 1892*1da177e4SLinus Torvalds unsigned long flags; 1893*1da177e4SLinus Torvalds struct lec_priv *priv = (struct lec_priv *)data; 1894*1da177e4SLinus Torvalds struct lec_arp_table *entry, *next; 1895*1da177e4SLinus Torvalds unsigned long now; 1896*1da177e4SLinus Torvalds unsigned long time_to_check; 1897*1da177e4SLinus Torvalds int i; 1898*1da177e4SLinus Torvalds 1899*1da177e4SLinus Torvalds DPRINTK("lec_arp_check_expire %p\n",priv); 1900*1da177e4SLinus Torvalds DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, 1901*1da177e4SLinus Torvalds priv->lec_no_forward); 1902*1da177e4SLinus Torvalds now = jiffies; 1903*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 1904*1da177e4SLinus Torvalds for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 1905*1da177e4SLinus Torvalds for(entry = priv->lec_arp_tables[i]; entry != NULL; ) { 1906*1da177e4SLinus Torvalds if ((entry->flags) & LEC_REMOTE_FLAG && 1907*1da177e4SLinus Torvalds priv->topology_change) 1908*1da177e4SLinus Torvalds time_to_check = priv->forward_delay_time; 1909*1da177e4SLinus Torvalds else 1910*1da177e4SLinus Torvalds time_to_check = priv->aging_time; 1911*1da177e4SLinus Torvalds 1912*1da177e4SLinus Torvalds DPRINTK("About to expire: %lx - %lx > %lx\n", 1913*1da177e4SLinus Torvalds now,entry->last_used, time_to_check); 1914*1da177e4SLinus Torvalds if( time_after(now, entry->last_used+ 1915*1da177e4SLinus Torvalds time_to_check) && 1916*1da177e4SLinus Torvalds !(entry->flags & LEC_PERMANENT_FLAG) && 1917*1da177e4SLinus Torvalds !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */ 1918*1da177e4SLinus Torvalds /* Remove entry */ 1919*1da177e4SLinus Torvalds DPRINTK("LEC:Entry timed out\n"); 1920*1da177e4SLinus Torvalds next = entry->next; 1921*1da177e4SLinus Torvalds lec_arp_remove(priv, entry); 1922*1da177e4SLinus Torvalds kfree(entry); 1923*1da177e4SLinus Torvalds entry = next; 1924*1da177e4SLinus Torvalds } else { 1925*1da177e4SLinus Torvalds /* Something else */ 1926*1da177e4SLinus Torvalds if ((entry->status == ESI_VC_PENDING || 1927*1da177e4SLinus Torvalds entry->status == ESI_ARP_PENDING) 1928*1da177e4SLinus Torvalds && time_after_eq(now, 1929*1da177e4SLinus Torvalds entry->timestamp + 1930*1da177e4SLinus Torvalds priv->max_unknown_frame_time)) { 1931*1da177e4SLinus Torvalds entry->timestamp = jiffies; 1932*1da177e4SLinus Torvalds entry->packets_flooded = 0; 1933*1da177e4SLinus Torvalds if (entry->status == ESI_VC_PENDING) 1934*1da177e4SLinus Torvalds send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL); 1935*1da177e4SLinus Torvalds } 1936*1da177e4SLinus Torvalds if (entry->status == ESI_FLUSH_PENDING 1937*1da177e4SLinus Torvalds && 1938*1da177e4SLinus Torvalds time_after_eq(now, entry->timestamp+ 1939*1da177e4SLinus Torvalds priv->path_switching_delay)) { 1940*1da177e4SLinus Torvalds struct sk_buff *skb; 1941*1da177e4SLinus Torvalds 1942*1da177e4SLinus Torvalds while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) 1943*1da177e4SLinus Torvalds lec_send(entry->vcc, skb, entry->priv); 1944*1da177e4SLinus Torvalds entry->last_used = jiffies; 1945*1da177e4SLinus Torvalds entry->status = 1946*1da177e4SLinus Torvalds ESI_FORWARD_DIRECT; 1947*1da177e4SLinus Torvalds } 1948*1da177e4SLinus Torvalds entry = entry->next; 1949*1da177e4SLinus Torvalds } 1950*1da177e4SLinus Torvalds } 1951*1da177e4SLinus Torvalds } 1952*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 1953*1da177e4SLinus Torvalds 1954*1da177e4SLinus Torvalds mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL); 1955*1da177e4SLinus Torvalds } 1956*1da177e4SLinus Torvalds /* 1957*1da177e4SLinus Torvalds * Try to find vcc where mac_address is attached. 1958*1da177e4SLinus Torvalds * 1959*1da177e4SLinus Torvalds */ 1960*1da177e4SLinus Torvalds static struct atm_vcc* 1961*1da177e4SLinus Torvalds lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, 1962*1da177e4SLinus Torvalds int is_rdesc, struct lec_arp_table **ret_entry) 1963*1da177e4SLinus Torvalds { 1964*1da177e4SLinus Torvalds unsigned long flags; 1965*1da177e4SLinus Torvalds struct lec_arp_table *entry; 1966*1da177e4SLinus Torvalds struct atm_vcc *found; 1967*1da177e4SLinus Torvalds 1968*1da177e4SLinus Torvalds if (mac_to_find[0] & 0x01) { 1969*1da177e4SLinus Torvalds switch (priv->lane_version) { 1970*1da177e4SLinus Torvalds case 1: 1971*1da177e4SLinus Torvalds return priv->mcast_vcc; 1972*1da177e4SLinus Torvalds break; 1973*1da177e4SLinus Torvalds case 2: /* LANE2 wants arp for multicast addresses */ 1974*1da177e4SLinus Torvalds if ( memcmp(mac_to_find, bus_mac, ETH_ALEN) == 0) 1975*1da177e4SLinus Torvalds return priv->mcast_vcc; 1976*1da177e4SLinus Torvalds break; 1977*1da177e4SLinus Torvalds default: 1978*1da177e4SLinus Torvalds break; 1979*1da177e4SLinus Torvalds } 1980*1da177e4SLinus Torvalds } 1981*1da177e4SLinus Torvalds 1982*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 1983*1da177e4SLinus Torvalds entry = lec_arp_find(priv, mac_to_find); 1984*1da177e4SLinus Torvalds 1985*1da177e4SLinus Torvalds if (entry) { 1986*1da177e4SLinus Torvalds if (entry->status == ESI_FORWARD_DIRECT) { 1987*1da177e4SLinus Torvalds /* Connection Ok */ 1988*1da177e4SLinus Torvalds entry->last_used = jiffies; 1989*1da177e4SLinus Torvalds *ret_entry = entry; 1990*1da177e4SLinus Torvalds found = entry->vcc; 1991*1da177e4SLinus Torvalds goto out; 1992*1da177e4SLinus Torvalds } 1993*1da177e4SLinus Torvalds /* Data direct VC not yet set up, check to see if the unknown 1994*1da177e4SLinus Torvalds frame count is greater than the limit. If the limit has 1995*1da177e4SLinus Torvalds not been reached, allow the caller to send packet to 1996*1da177e4SLinus Torvalds BUS. */ 1997*1da177e4SLinus Torvalds if (entry->status != ESI_FLUSH_PENDING && 1998*1da177e4SLinus Torvalds entry->packets_flooded<priv->maximum_unknown_frame_count) { 1999*1da177e4SLinus Torvalds entry->packets_flooded++; 2000*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Flooding..\n"); 2001*1da177e4SLinus Torvalds found = priv->mcast_vcc; 2002*1da177e4SLinus Torvalds goto out; 2003*1da177e4SLinus Torvalds } 2004*1da177e4SLinus Torvalds /* We got here because entry->status == ESI_FLUSH_PENDING 2005*1da177e4SLinus Torvalds * or BUS flood limit was reached for an entry which is 2006*1da177e4SLinus Torvalds * in ESI_ARP_PENDING or ESI_VC_PENDING state. 2007*1da177e4SLinus Torvalds */ 2008*1da177e4SLinus Torvalds *ret_entry = entry; 2009*1da177e4SLinus Torvalds DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc); 2010*1da177e4SLinus Torvalds found = NULL; 2011*1da177e4SLinus Torvalds } else { 2012*1da177e4SLinus Torvalds /* No matching entry was found */ 2013*1da177e4SLinus Torvalds entry = make_entry(priv, mac_to_find); 2014*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Making entry\n"); 2015*1da177e4SLinus Torvalds if (!entry) { 2016*1da177e4SLinus Torvalds found = priv->mcast_vcc; 2017*1da177e4SLinus Torvalds goto out; 2018*1da177e4SLinus Torvalds } 2019*1da177e4SLinus Torvalds lec_arp_add(priv, entry); 2020*1da177e4SLinus Torvalds /* We want arp-request(s) to be sent */ 2021*1da177e4SLinus Torvalds entry->packets_flooded =1; 2022*1da177e4SLinus Torvalds entry->status = ESI_ARP_PENDING; 2023*1da177e4SLinus Torvalds entry->no_tries = 1; 2024*1da177e4SLinus Torvalds entry->last_used = entry->timestamp = jiffies; 2025*1da177e4SLinus Torvalds entry->is_rdesc = is_rdesc; 2026*1da177e4SLinus Torvalds if (entry->is_rdesc) 2027*1da177e4SLinus Torvalds send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL); 2028*1da177e4SLinus Torvalds else 2029*1da177e4SLinus Torvalds send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); 2030*1da177e4SLinus Torvalds entry->timer.expires = jiffies + (1*HZ); 2031*1da177e4SLinus Torvalds entry->timer.function = lec_arp_expire_arp; 2032*1da177e4SLinus Torvalds add_timer(&entry->timer); 2033*1da177e4SLinus Torvalds found = priv->mcast_vcc; 2034*1da177e4SLinus Torvalds } 2035*1da177e4SLinus Torvalds 2036*1da177e4SLinus Torvalds out: 2037*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2038*1da177e4SLinus Torvalds return found; 2039*1da177e4SLinus Torvalds } 2040*1da177e4SLinus Torvalds 2041*1da177e4SLinus Torvalds static int 2042*1da177e4SLinus Torvalds lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, 2043*1da177e4SLinus Torvalds unsigned long permanent) 2044*1da177e4SLinus Torvalds { 2045*1da177e4SLinus Torvalds unsigned long flags; 2046*1da177e4SLinus Torvalds struct lec_arp_table *entry, *next; 2047*1da177e4SLinus Torvalds int i; 2048*1da177e4SLinus Torvalds 2049*1da177e4SLinus Torvalds DPRINTK("lec_addr_delete\n"); 2050*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2051*1da177e4SLinus Torvalds for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 2052*1da177e4SLinus Torvalds for(entry = priv->lec_arp_tables[i]; entry != NULL; entry = next) { 2053*1da177e4SLinus Torvalds next = entry->next; 2054*1da177e4SLinus Torvalds if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) 2055*1da177e4SLinus Torvalds && (permanent || 2056*1da177e4SLinus Torvalds !(entry->flags & LEC_PERMANENT_FLAG))) { 2057*1da177e4SLinus Torvalds lec_arp_remove(priv, entry); 2058*1da177e4SLinus Torvalds kfree(entry); 2059*1da177e4SLinus Torvalds } 2060*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2061*1da177e4SLinus Torvalds return 0; 2062*1da177e4SLinus Torvalds } 2063*1da177e4SLinus Torvalds } 2064*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2065*1da177e4SLinus Torvalds return -1; 2066*1da177e4SLinus Torvalds } 2067*1da177e4SLinus Torvalds 2068*1da177e4SLinus Torvalds /* 2069*1da177e4SLinus Torvalds * Notifies: Response to arp_request (atm_addr != NULL) 2070*1da177e4SLinus Torvalds */ 2071*1da177e4SLinus Torvalds static void 2072*1da177e4SLinus Torvalds lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, 2073*1da177e4SLinus Torvalds unsigned char *atm_addr, unsigned long remoteflag, 2074*1da177e4SLinus Torvalds unsigned int targetless_le_arp) 2075*1da177e4SLinus Torvalds { 2076*1da177e4SLinus Torvalds unsigned long flags; 2077*1da177e4SLinus Torvalds struct lec_arp_table *entry, *tmp; 2078*1da177e4SLinus Torvalds int i; 2079*1da177e4SLinus Torvalds 2080*1da177e4SLinus Torvalds DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " "); 2081*1da177e4SLinus Torvalds DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", 2082*1da177e4SLinus Torvalds mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3], 2083*1da177e4SLinus Torvalds mac_addr[4],mac_addr[5]); 2084*1da177e4SLinus Torvalds 2085*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2086*1da177e4SLinus Torvalds entry = lec_arp_find(priv, mac_addr); 2087*1da177e4SLinus Torvalds if (entry == NULL && targetless_le_arp) 2088*1da177e4SLinus Torvalds goto out; /* LANE2: ignore targetless LE_ARPs for which 2089*1da177e4SLinus Torvalds * we have no entry in the cache. 7.1.30 2090*1da177e4SLinus Torvalds */ 2091*1da177e4SLinus Torvalds if (priv->lec_arp_empty_ones) { 2092*1da177e4SLinus Torvalds entry = priv->lec_arp_empty_ones; 2093*1da177e4SLinus Torvalds if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { 2094*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = entry->next; 2095*1da177e4SLinus Torvalds } else { 2096*1da177e4SLinus Torvalds while(entry->next && memcmp(entry->next->atm_addr, 2097*1da177e4SLinus Torvalds atm_addr, ATM_ESA_LEN)) 2098*1da177e4SLinus Torvalds entry = entry->next; 2099*1da177e4SLinus Torvalds if (entry->next) { 2100*1da177e4SLinus Torvalds tmp = entry; 2101*1da177e4SLinus Torvalds entry = entry->next; 2102*1da177e4SLinus Torvalds tmp->next = entry->next; 2103*1da177e4SLinus Torvalds } else 2104*1da177e4SLinus Torvalds entry = NULL; 2105*1da177e4SLinus Torvalds 2106*1da177e4SLinus Torvalds } 2107*1da177e4SLinus Torvalds if (entry) { 2108*1da177e4SLinus Torvalds del_timer(&entry->timer); 2109*1da177e4SLinus Torvalds tmp = lec_arp_find(priv, mac_addr); 2110*1da177e4SLinus Torvalds if (tmp) { 2111*1da177e4SLinus Torvalds del_timer(&tmp->timer); 2112*1da177e4SLinus Torvalds tmp->status = ESI_FORWARD_DIRECT; 2113*1da177e4SLinus Torvalds memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); 2114*1da177e4SLinus Torvalds tmp->vcc = entry->vcc; 2115*1da177e4SLinus Torvalds tmp->old_push = entry->old_push; 2116*1da177e4SLinus Torvalds tmp->last_used = jiffies; 2117*1da177e4SLinus Torvalds del_timer(&entry->timer); 2118*1da177e4SLinus Torvalds kfree(entry); 2119*1da177e4SLinus Torvalds entry=tmp; 2120*1da177e4SLinus Torvalds } else { 2121*1da177e4SLinus Torvalds entry->status = ESI_FORWARD_DIRECT; 2122*1da177e4SLinus Torvalds memcpy(entry->mac_addr, mac_addr, ETH_ALEN); 2123*1da177e4SLinus Torvalds entry->last_used = jiffies; 2124*1da177e4SLinus Torvalds lec_arp_add(priv, entry); 2125*1da177e4SLinus Torvalds } 2126*1da177e4SLinus Torvalds if (remoteflag) 2127*1da177e4SLinus Torvalds entry->flags|=LEC_REMOTE_FLAG; 2128*1da177e4SLinus Torvalds else 2129*1da177e4SLinus Torvalds entry->flags&=~LEC_REMOTE_FLAG; 2130*1da177e4SLinus Torvalds DPRINTK("After update\n"); 2131*1da177e4SLinus Torvalds dump_arp_table(priv); 2132*1da177e4SLinus Torvalds goto out; 2133*1da177e4SLinus Torvalds } 2134*1da177e4SLinus Torvalds } 2135*1da177e4SLinus Torvalds entry = lec_arp_find(priv, mac_addr); 2136*1da177e4SLinus Torvalds if (!entry) { 2137*1da177e4SLinus Torvalds entry = make_entry(priv, mac_addr); 2138*1da177e4SLinus Torvalds if (!entry) 2139*1da177e4SLinus Torvalds goto out; 2140*1da177e4SLinus Torvalds entry->status = ESI_UNKNOWN; 2141*1da177e4SLinus Torvalds lec_arp_add(priv, entry); 2142*1da177e4SLinus Torvalds /* Temporary, changes before end of function */ 2143*1da177e4SLinus Torvalds } 2144*1da177e4SLinus Torvalds memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); 2145*1da177e4SLinus Torvalds del_timer(&entry->timer); 2146*1da177e4SLinus Torvalds for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 2147*1da177e4SLinus Torvalds for(tmp = priv->lec_arp_tables[i]; tmp; tmp=tmp->next) { 2148*1da177e4SLinus Torvalds if (entry != tmp && 2149*1da177e4SLinus Torvalds !memcmp(tmp->atm_addr, atm_addr, 2150*1da177e4SLinus Torvalds ATM_ESA_LEN)) { 2151*1da177e4SLinus Torvalds /* Vcc to this host exists */ 2152*1da177e4SLinus Torvalds if (tmp->status > ESI_VC_PENDING) { 2153*1da177e4SLinus Torvalds /* 2154*1da177e4SLinus Torvalds * ESI_FLUSH_PENDING, 2155*1da177e4SLinus Torvalds * ESI_FORWARD_DIRECT 2156*1da177e4SLinus Torvalds */ 2157*1da177e4SLinus Torvalds entry->vcc = tmp->vcc; 2158*1da177e4SLinus Torvalds entry->old_push=tmp->old_push; 2159*1da177e4SLinus Torvalds } 2160*1da177e4SLinus Torvalds entry->status=tmp->status; 2161*1da177e4SLinus Torvalds break; 2162*1da177e4SLinus Torvalds } 2163*1da177e4SLinus Torvalds } 2164*1da177e4SLinus Torvalds } 2165*1da177e4SLinus Torvalds if (remoteflag) 2166*1da177e4SLinus Torvalds entry->flags|=LEC_REMOTE_FLAG; 2167*1da177e4SLinus Torvalds else 2168*1da177e4SLinus Torvalds entry->flags&=~LEC_REMOTE_FLAG; 2169*1da177e4SLinus Torvalds if (entry->status == ESI_ARP_PENDING || 2170*1da177e4SLinus Torvalds entry->status == ESI_UNKNOWN) { 2171*1da177e4SLinus Torvalds entry->status = ESI_VC_PENDING; 2172*1da177e4SLinus Torvalds send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL); 2173*1da177e4SLinus Torvalds } 2174*1da177e4SLinus Torvalds DPRINTK("After update2\n"); 2175*1da177e4SLinus Torvalds dump_arp_table(priv); 2176*1da177e4SLinus Torvalds out: 2177*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2178*1da177e4SLinus Torvalds } 2179*1da177e4SLinus Torvalds 2180*1da177e4SLinus Torvalds /* 2181*1da177e4SLinus Torvalds * Notifies: Vcc setup ready 2182*1da177e4SLinus Torvalds */ 2183*1da177e4SLinus Torvalds static void 2184*1da177e4SLinus Torvalds lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, 2185*1da177e4SLinus Torvalds struct atm_vcc *vcc, 2186*1da177e4SLinus Torvalds void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)) 2187*1da177e4SLinus Torvalds { 2188*1da177e4SLinus Torvalds unsigned long flags; 2189*1da177e4SLinus Torvalds struct lec_arp_table *entry; 2190*1da177e4SLinus Torvalds int i, found_entry=0; 2191*1da177e4SLinus Torvalds 2192*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2193*1da177e4SLinus Torvalds if (ioc_data->receive == 2) { 2194*1da177e4SLinus Torvalds /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */ 2195*1da177e4SLinus Torvalds 2196*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Attaching mcast forward\n"); 2197*1da177e4SLinus Torvalds #if 0 2198*1da177e4SLinus Torvalds entry = lec_arp_find(priv, bus_mac); 2199*1da177e4SLinus Torvalds if (!entry) { 2200*1da177e4SLinus Torvalds printk("LEC_ARP: Multicast entry not found!\n"); 2201*1da177e4SLinus Torvalds goto out; 2202*1da177e4SLinus Torvalds } 2203*1da177e4SLinus Torvalds memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); 2204*1da177e4SLinus Torvalds entry->recv_vcc = vcc; 2205*1da177e4SLinus Torvalds entry->old_recv_push = old_push; 2206*1da177e4SLinus Torvalds #endif 2207*1da177e4SLinus Torvalds entry = make_entry(priv, bus_mac); 2208*1da177e4SLinus Torvalds if (entry == NULL) 2209*1da177e4SLinus Torvalds goto out; 2210*1da177e4SLinus Torvalds del_timer(&entry->timer); 2211*1da177e4SLinus Torvalds memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); 2212*1da177e4SLinus Torvalds entry->recv_vcc = vcc; 2213*1da177e4SLinus Torvalds entry->old_recv_push = old_push; 2214*1da177e4SLinus Torvalds entry->next = priv->mcast_fwds; 2215*1da177e4SLinus Torvalds priv->mcast_fwds = entry; 2216*1da177e4SLinus Torvalds goto out; 2217*1da177e4SLinus Torvalds } else if (ioc_data->receive == 1) { 2218*1da177e4SLinus Torvalds /* Vcc which we don't want to make default vcc, attach it 2219*1da177e4SLinus Torvalds anyway. */ 2220*1da177e4SLinus Torvalds 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", 2221*1da177e4SLinus Torvalds ioc_data->atm_addr[0],ioc_data->atm_addr[1], 2222*1da177e4SLinus Torvalds ioc_data->atm_addr[2],ioc_data->atm_addr[3], 2223*1da177e4SLinus Torvalds ioc_data->atm_addr[4],ioc_data->atm_addr[5], 2224*1da177e4SLinus Torvalds ioc_data->atm_addr[6],ioc_data->atm_addr[7], 2225*1da177e4SLinus Torvalds ioc_data->atm_addr[8],ioc_data->atm_addr[9], 2226*1da177e4SLinus Torvalds ioc_data->atm_addr[10],ioc_data->atm_addr[11], 2227*1da177e4SLinus Torvalds ioc_data->atm_addr[12],ioc_data->atm_addr[13], 2228*1da177e4SLinus Torvalds ioc_data->atm_addr[14],ioc_data->atm_addr[15], 2229*1da177e4SLinus Torvalds ioc_data->atm_addr[16],ioc_data->atm_addr[17], 2230*1da177e4SLinus Torvalds ioc_data->atm_addr[18],ioc_data->atm_addr[19]); 2231*1da177e4SLinus Torvalds entry = make_entry(priv, bus_mac); 2232*1da177e4SLinus Torvalds if (entry == NULL) 2233*1da177e4SLinus Torvalds goto out; 2234*1da177e4SLinus Torvalds memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); 2235*1da177e4SLinus Torvalds memset(entry->mac_addr, 0, ETH_ALEN); 2236*1da177e4SLinus Torvalds entry->recv_vcc = vcc; 2237*1da177e4SLinus Torvalds entry->old_recv_push = old_push; 2238*1da177e4SLinus Torvalds entry->status = ESI_UNKNOWN; 2239*1da177e4SLinus Torvalds entry->timer.expires = jiffies + priv->vcc_timeout_period; 2240*1da177e4SLinus Torvalds entry->timer.function = lec_arp_expire_vcc; 2241*1da177e4SLinus Torvalds add_timer(&entry->timer); 2242*1da177e4SLinus Torvalds entry->next = priv->lec_no_forward; 2243*1da177e4SLinus Torvalds priv->lec_no_forward = entry; 2244*1da177e4SLinus Torvalds dump_arp_table(priv); 2245*1da177e4SLinus Torvalds goto out; 2246*1da177e4SLinus Torvalds } 2247*1da177e4SLinus Torvalds 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", 2248*1da177e4SLinus Torvalds ioc_data->atm_addr[0],ioc_data->atm_addr[1], 2249*1da177e4SLinus Torvalds ioc_data->atm_addr[2],ioc_data->atm_addr[3], 2250*1da177e4SLinus Torvalds ioc_data->atm_addr[4],ioc_data->atm_addr[5], 2251*1da177e4SLinus Torvalds ioc_data->atm_addr[6],ioc_data->atm_addr[7], 2252*1da177e4SLinus Torvalds ioc_data->atm_addr[8],ioc_data->atm_addr[9], 2253*1da177e4SLinus Torvalds ioc_data->atm_addr[10],ioc_data->atm_addr[11], 2254*1da177e4SLinus Torvalds ioc_data->atm_addr[12],ioc_data->atm_addr[13], 2255*1da177e4SLinus Torvalds ioc_data->atm_addr[14],ioc_data->atm_addr[15], 2256*1da177e4SLinus Torvalds ioc_data->atm_addr[16],ioc_data->atm_addr[17], 2257*1da177e4SLinus Torvalds ioc_data->atm_addr[18],ioc_data->atm_addr[19]); 2258*1da177e4SLinus Torvalds for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 2259*1da177e4SLinus Torvalds for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) { 2260*1da177e4SLinus Torvalds if (memcmp(ioc_data->atm_addr, entry->atm_addr, 2261*1da177e4SLinus Torvalds ATM_ESA_LEN)==0) { 2262*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Attaching data direct\n"); 2263*1da177e4SLinus Torvalds DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n", 2264*1da177e4SLinus Torvalds entry->vcc?entry->vcc->vci:0, 2265*1da177e4SLinus Torvalds entry->recv_vcc?entry->recv_vcc->vci:0); 2266*1da177e4SLinus Torvalds found_entry=1; 2267*1da177e4SLinus Torvalds del_timer(&entry->timer); 2268*1da177e4SLinus Torvalds entry->vcc = vcc; 2269*1da177e4SLinus Torvalds entry->old_push = old_push; 2270*1da177e4SLinus Torvalds if (entry->status == ESI_VC_PENDING) { 2271*1da177e4SLinus Torvalds if(priv->maximum_unknown_frame_count 2272*1da177e4SLinus Torvalds ==0) 2273*1da177e4SLinus Torvalds entry->status = 2274*1da177e4SLinus Torvalds ESI_FORWARD_DIRECT; 2275*1da177e4SLinus Torvalds else { 2276*1da177e4SLinus Torvalds entry->timestamp = jiffies; 2277*1da177e4SLinus Torvalds entry->status = 2278*1da177e4SLinus Torvalds ESI_FLUSH_PENDING; 2279*1da177e4SLinus Torvalds #if 0 2280*1da177e4SLinus Torvalds send_to_lecd(priv,l_flush_xmt, 2281*1da177e4SLinus Torvalds NULL, 2282*1da177e4SLinus Torvalds entry->atm_addr, 2283*1da177e4SLinus Torvalds NULL); 2284*1da177e4SLinus Torvalds #endif 2285*1da177e4SLinus Torvalds } 2286*1da177e4SLinus Torvalds } else { 2287*1da177e4SLinus Torvalds /* They were forming a connection 2288*1da177e4SLinus Torvalds to us, and we to them. Our 2289*1da177e4SLinus Torvalds ATM address is numerically lower 2290*1da177e4SLinus Torvalds than theirs, so we make connection 2291*1da177e4SLinus Torvalds we formed into default VCC (8.1.11). 2292*1da177e4SLinus Torvalds Connection they made gets torn 2293*1da177e4SLinus Torvalds down. This might confuse some 2294*1da177e4SLinus Torvalds clients. Can be changed if 2295*1da177e4SLinus Torvalds someone reports trouble... */ 2296*1da177e4SLinus Torvalds ; 2297*1da177e4SLinus Torvalds } 2298*1da177e4SLinus Torvalds } 2299*1da177e4SLinus Torvalds } 2300*1da177e4SLinus Torvalds } 2301*1da177e4SLinus Torvalds if (found_entry) { 2302*1da177e4SLinus Torvalds DPRINTK("After vcc was added\n"); 2303*1da177e4SLinus Torvalds dump_arp_table(priv); 2304*1da177e4SLinus Torvalds goto out; 2305*1da177e4SLinus Torvalds } 2306*1da177e4SLinus Torvalds /* Not found, snatch address from first data packet that arrives from 2307*1da177e4SLinus Torvalds this vcc */ 2308*1da177e4SLinus Torvalds entry = make_entry(priv, bus_mac); 2309*1da177e4SLinus Torvalds if (!entry) 2310*1da177e4SLinus Torvalds goto out; 2311*1da177e4SLinus Torvalds entry->vcc = vcc; 2312*1da177e4SLinus Torvalds entry->old_push = old_push; 2313*1da177e4SLinus Torvalds memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); 2314*1da177e4SLinus Torvalds memset(entry->mac_addr, 0, ETH_ALEN); 2315*1da177e4SLinus Torvalds entry->status = ESI_UNKNOWN; 2316*1da177e4SLinus Torvalds entry->next = priv->lec_arp_empty_ones; 2317*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = entry; 2318*1da177e4SLinus Torvalds entry->timer.expires = jiffies + priv->vcc_timeout_period; 2319*1da177e4SLinus Torvalds entry->timer.function = lec_arp_expire_vcc; 2320*1da177e4SLinus Torvalds add_timer(&entry->timer); 2321*1da177e4SLinus Torvalds DPRINTK("After vcc was added\n"); 2322*1da177e4SLinus Torvalds dump_arp_table(priv); 2323*1da177e4SLinus Torvalds out: 2324*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2325*1da177e4SLinus Torvalds } 2326*1da177e4SLinus Torvalds 2327*1da177e4SLinus Torvalds static void 2328*1da177e4SLinus Torvalds lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) 2329*1da177e4SLinus Torvalds { 2330*1da177e4SLinus Torvalds unsigned long flags; 2331*1da177e4SLinus Torvalds struct lec_arp_table *entry; 2332*1da177e4SLinus Torvalds int i; 2333*1da177e4SLinus Torvalds 2334*1da177e4SLinus Torvalds DPRINTK("LEC:lec_flush_complete %lx\n",tran_id); 2335*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2336*1da177e4SLinus Torvalds for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { 2337*1da177e4SLinus Torvalds for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) { 2338*1da177e4SLinus Torvalds if (entry->flush_tran_id == tran_id && 2339*1da177e4SLinus Torvalds entry->status == ESI_FLUSH_PENDING) { 2340*1da177e4SLinus Torvalds struct sk_buff *skb; 2341*1da177e4SLinus Torvalds 2342*1da177e4SLinus Torvalds while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) 2343*1da177e4SLinus Torvalds lec_send(entry->vcc, skb, entry->priv); 2344*1da177e4SLinus Torvalds entry->status = ESI_FORWARD_DIRECT; 2345*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Flushed\n"); 2346*1da177e4SLinus Torvalds } 2347*1da177e4SLinus Torvalds } 2348*1da177e4SLinus Torvalds } 2349*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2350*1da177e4SLinus Torvalds dump_arp_table(priv); 2351*1da177e4SLinus Torvalds } 2352*1da177e4SLinus Torvalds 2353*1da177e4SLinus Torvalds static void 2354*1da177e4SLinus Torvalds lec_set_flush_tran_id(struct lec_priv *priv, 2355*1da177e4SLinus Torvalds unsigned char *atm_addr, unsigned long tran_id) 2356*1da177e4SLinus Torvalds { 2357*1da177e4SLinus Torvalds unsigned long flags; 2358*1da177e4SLinus Torvalds struct lec_arp_table *entry; 2359*1da177e4SLinus Torvalds int i; 2360*1da177e4SLinus Torvalds 2361*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2362*1da177e4SLinus Torvalds for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) 2363*1da177e4SLinus Torvalds for(entry = priv->lec_arp_tables[i]; entry; entry=entry->next) 2364*1da177e4SLinus Torvalds if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { 2365*1da177e4SLinus Torvalds entry->flush_tran_id = tran_id; 2366*1da177e4SLinus Torvalds DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry); 2367*1da177e4SLinus Torvalds } 2368*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2369*1da177e4SLinus Torvalds } 2370*1da177e4SLinus Torvalds 2371*1da177e4SLinus Torvalds static int 2372*1da177e4SLinus Torvalds lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) 2373*1da177e4SLinus Torvalds { 2374*1da177e4SLinus Torvalds unsigned long flags; 2375*1da177e4SLinus Torvalds unsigned char mac_addr[] = { 2376*1da177e4SLinus Torvalds 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 2377*1da177e4SLinus Torvalds struct lec_arp_table *to_add; 2378*1da177e4SLinus Torvalds struct lec_vcc_priv *vpriv; 2379*1da177e4SLinus Torvalds int err = 0; 2380*1da177e4SLinus Torvalds 2381*1da177e4SLinus Torvalds if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) 2382*1da177e4SLinus Torvalds return -ENOMEM; 2383*1da177e4SLinus Torvalds vpriv->xoff = 0; 2384*1da177e4SLinus Torvalds vpriv->old_pop = vcc->pop; 2385*1da177e4SLinus Torvalds vcc->user_back = vpriv; 2386*1da177e4SLinus Torvalds vcc->pop = lec_pop; 2387*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2388*1da177e4SLinus Torvalds to_add = make_entry(priv, mac_addr); 2389*1da177e4SLinus Torvalds if (!to_add) { 2390*1da177e4SLinus Torvalds vcc->pop = vpriv->old_pop; 2391*1da177e4SLinus Torvalds kfree(vpriv); 2392*1da177e4SLinus Torvalds err = -ENOMEM; 2393*1da177e4SLinus Torvalds goto out; 2394*1da177e4SLinus Torvalds } 2395*1da177e4SLinus Torvalds memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN); 2396*1da177e4SLinus Torvalds to_add->status = ESI_FORWARD_DIRECT; 2397*1da177e4SLinus Torvalds to_add->flags |= LEC_PERMANENT_FLAG; 2398*1da177e4SLinus Torvalds to_add->vcc = vcc; 2399*1da177e4SLinus Torvalds to_add->old_push = vcc->push; 2400*1da177e4SLinus Torvalds vcc->push = lec_push; 2401*1da177e4SLinus Torvalds priv->mcast_vcc = vcc; 2402*1da177e4SLinus Torvalds lec_arp_add(priv, to_add); 2403*1da177e4SLinus Torvalds out: 2404*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2405*1da177e4SLinus Torvalds return err; 2406*1da177e4SLinus Torvalds } 2407*1da177e4SLinus Torvalds 2408*1da177e4SLinus Torvalds static void 2409*1da177e4SLinus Torvalds lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) 2410*1da177e4SLinus Torvalds { 2411*1da177e4SLinus Torvalds unsigned long flags; 2412*1da177e4SLinus Torvalds struct lec_arp_table *entry, *next; 2413*1da177e4SLinus Torvalds int i; 2414*1da177e4SLinus Torvalds 2415*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci); 2416*1da177e4SLinus Torvalds dump_arp_table(priv); 2417*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2418*1da177e4SLinus Torvalds for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { 2419*1da177e4SLinus Torvalds for(entry = priv->lec_arp_tables[i];entry; entry=next) { 2420*1da177e4SLinus Torvalds next = entry->next; 2421*1da177e4SLinus Torvalds if (vcc == entry->vcc) { 2422*1da177e4SLinus Torvalds lec_arp_remove(priv, entry); 2423*1da177e4SLinus Torvalds kfree(entry); 2424*1da177e4SLinus Torvalds if (priv->mcast_vcc == vcc) { 2425*1da177e4SLinus Torvalds priv->mcast_vcc = NULL; 2426*1da177e4SLinus Torvalds } 2427*1da177e4SLinus Torvalds } 2428*1da177e4SLinus Torvalds } 2429*1da177e4SLinus Torvalds } 2430*1da177e4SLinus Torvalds 2431*1da177e4SLinus Torvalds entry = priv->lec_arp_empty_ones; 2432*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = NULL; 2433*1da177e4SLinus Torvalds while (entry != NULL) { 2434*1da177e4SLinus Torvalds next = entry->next; 2435*1da177e4SLinus Torvalds if (entry->vcc == vcc) { /* leave it out from the list */ 2436*1da177e4SLinus Torvalds lec_arp_clear_vccs(entry); 2437*1da177e4SLinus Torvalds del_timer(&entry->timer); 2438*1da177e4SLinus Torvalds kfree(entry); 2439*1da177e4SLinus Torvalds } 2440*1da177e4SLinus Torvalds else { /* put it back to the list */ 2441*1da177e4SLinus Torvalds entry->next = priv->lec_arp_empty_ones; 2442*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = entry; 2443*1da177e4SLinus Torvalds } 2444*1da177e4SLinus Torvalds entry = next; 2445*1da177e4SLinus Torvalds } 2446*1da177e4SLinus Torvalds 2447*1da177e4SLinus Torvalds entry = priv->lec_no_forward; 2448*1da177e4SLinus Torvalds priv->lec_no_forward = NULL; 2449*1da177e4SLinus Torvalds while (entry != NULL) { 2450*1da177e4SLinus Torvalds next = entry->next; 2451*1da177e4SLinus Torvalds if (entry->recv_vcc == vcc) { 2452*1da177e4SLinus Torvalds lec_arp_clear_vccs(entry); 2453*1da177e4SLinus Torvalds del_timer(&entry->timer); 2454*1da177e4SLinus Torvalds kfree(entry); 2455*1da177e4SLinus Torvalds } 2456*1da177e4SLinus Torvalds else { 2457*1da177e4SLinus Torvalds entry->next = priv->lec_no_forward; 2458*1da177e4SLinus Torvalds priv->lec_no_forward = entry; 2459*1da177e4SLinus Torvalds } 2460*1da177e4SLinus Torvalds entry = next; 2461*1da177e4SLinus Torvalds } 2462*1da177e4SLinus Torvalds 2463*1da177e4SLinus Torvalds entry = priv->mcast_fwds; 2464*1da177e4SLinus Torvalds priv->mcast_fwds = NULL; 2465*1da177e4SLinus Torvalds while (entry != NULL) { 2466*1da177e4SLinus Torvalds next = entry->next; 2467*1da177e4SLinus Torvalds if (entry->recv_vcc == vcc) { 2468*1da177e4SLinus Torvalds lec_arp_clear_vccs(entry); 2469*1da177e4SLinus Torvalds /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ 2470*1da177e4SLinus Torvalds kfree(entry); 2471*1da177e4SLinus Torvalds } 2472*1da177e4SLinus Torvalds else { 2473*1da177e4SLinus Torvalds entry->next = priv->mcast_fwds; 2474*1da177e4SLinus Torvalds priv->mcast_fwds = entry; 2475*1da177e4SLinus Torvalds } 2476*1da177e4SLinus Torvalds entry = next; 2477*1da177e4SLinus Torvalds } 2478*1da177e4SLinus Torvalds 2479*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2480*1da177e4SLinus Torvalds dump_arp_table(priv); 2481*1da177e4SLinus Torvalds } 2482*1da177e4SLinus Torvalds 2483*1da177e4SLinus Torvalds static void 2484*1da177e4SLinus Torvalds lec_arp_check_empties(struct lec_priv *priv, 2485*1da177e4SLinus Torvalds struct atm_vcc *vcc, struct sk_buff *skb) 2486*1da177e4SLinus Torvalds { 2487*1da177e4SLinus Torvalds unsigned long flags; 2488*1da177e4SLinus Torvalds struct lec_arp_table *entry, *prev; 2489*1da177e4SLinus Torvalds struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; 2490*1da177e4SLinus Torvalds unsigned char *src; 2491*1da177e4SLinus Torvalds #ifdef CONFIG_TR 2492*1da177e4SLinus Torvalds struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data; 2493*1da177e4SLinus Torvalds 2494*1da177e4SLinus Torvalds if (priv->is_trdev) src = tr_hdr->h_source; 2495*1da177e4SLinus Torvalds else 2496*1da177e4SLinus Torvalds #endif 2497*1da177e4SLinus Torvalds src = hdr->h_source; 2498*1da177e4SLinus Torvalds 2499*1da177e4SLinus Torvalds spin_lock_irqsave(&priv->lec_arp_lock, flags); 2500*1da177e4SLinus Torvalds entry = priv->lec_arp_empty_ones; 2501*1da177e4SLinus Torvalds if (vcc == entry->vcc) { 2502*1da177e4SLinus Torvalds del_timer(&entry->timer); 2503*1da177e4SLinus Torvalds memcpy(entry->mac_addr, src, ETH_ALEN); 2504*1da177e4SLinus Torvalds entry->status = ESI_FORWARD_DIRECT; 2505*1da177e4SLinus Torvalds entry->last_used = jiffies; 2506*1da177e4SLinus Torvalds priv->lec_arp_empty_ones = entry->next; 2507*1da177e4SLinus Torvalds /* We might have got an entry */ 2508*1da177e4SLinus Torvalds if ((prev = lec_arp_find(priv,src))) { 2509*1da177e4SLinus Torvalds lec_arp_remove(priv, prev); 2510*1da177e4SLinus Torvalds kfree(prev); 2511*1da177e4SLinus Torvalds } 2512*1da177e4SLinus Torvalds lec_arp_add(priv, entry); 2513*1da177e4SLinus Torvalds goto out; 2514*1da177e4SLinus Torvalds } 2515*1da177e4SLinus Torvalds prev = entry; 2516*1da177e4SLinus Torvalds entry = entry->next; 2517*1da177e4SLinus Torvalds while (entry && entry->vcc != vcc) { 2518*1da177e4SLinus Torvalds prev= entry; 2519*1da177e4SLinus Torvalds entry = entry->next; 2520*1da177e4SLinus Torvalds } 2521*1da177e4SLinus Torvalds if (!entry) { 2522*1da177e4SLinus Torvalds DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); 2523*1da177e4SLinus Torvalds goto out; 2524*1da177e4SLinus Torvalds } 2525*1da177e4SLinus Torvalds del_timer(&entry->timer); 2526*1da177e4SLinus Torvalds memcpy(entry->mac_addr, src, ETH_ALEN); 2527*1da177e4SLinus Torvalds entry->status = ESI_FORWARD_DIRECT; 2528*1da177e4SLinus Torvalds entry->last_used = jiffies; 2529*1da177e4SLinus Torvalds prev->next = entry->next; 2530*1da177e4SLinus Torvalds if ((prev = lec_arp_find(priv, src))) { 2531*1da177e4SLinus Torvalds lec_arp_remove(priv, prev); 2532*1da177e4SLinus Torvalds kfree(prev); 2533*1da177e4SLinus Torvalds } 2534*1da177e4SLinus Torvalds lec_arp_add(priv, entry); 2535*1da177e4SLinus Torvalds out: 2536*1da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lec_arp_lock, flags); 2537*1da177e4SLinus Torvalds } 2538*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 2539