📄 lec.c
字号:
deregister_atm_ioctl(&lane_ioctl_ops); for (i = 0; i < MAX_LEC_ITF; i++) { if (dev_lec[i] != NULL) { priv = (struct lec_priv *)dev_lec[i]->priv; unregister_netdev(dev_lec[i]); free_netdev(dev_lec[i]); dev_lec[i] = NULL; } } return; }module_init(lane_module_init);module_exit(lane_module_cleanup);/* * LANE2: 3.1.3, LE_RESOLVE.request * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs. * If sizeoftlvs == NULL the default TLVs associated with with this * lec will be used. * If dst_mac == NULL, targetless LE_ARP will be sent */static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force, u8 **tlvs, u32 *sizeoftlvs){ struct lec_priv *priv = (struct lec_priv *)dev->priv; struct lec_arp_table *table; struct sk_buff *skb; int retval; if (force == 0) { table = lec_arp_find(priv, dst_mac); if(table == NULL) return -1; *tlvs = kmalloc(table->sizeoftlvs, GFP_KERNEL); if (*tlvs == NULL) return -1; memcpy(*tlvs, table->tlvs, table->sizeoftlvs); *sizeoftlvs = table->sizeoftlvs; return 0; } if (sizeoftlvs == NULL) retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL); else { skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC); if (skb == NULL) return -1; skb->len = *sizeoftlvs; memcpy(skb->data, *tlvs, *sizeoftlvs); retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb); } return retval;} /* * LANE2: 3.1.4, LE_ASSOCIATE.request * Associate the *tlvs with the *lan_dst address. * Will overwrite any previous association * Returns 1 for success, 0 for failure (out of memory) * */static int lane2_associate_req (struct net_device *dev, u8 *lan_dst, u8 *tlvs, u32 sizeoftlvs){ int retval; struct sk_buff *skb; struct lec_priv *priv = (struct lec_priv*)dev->priv; if ( memcmp(lan_dst, dev->dev_addr, ETH_ALEN) != 0 ) return (0); /* not our mac address */ kfree(priv->tlvs); /* NULL if there was no previous association */ priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); if (priv->tlvs == NULL) return (0); priv->sizeoftlvs = sizeoftlvs; memcpy(priv->tlvs, tlvs, sizeoftlvs); skb = alloc_skb(sizeoftlvs, GFP_ATOMIC); if (skb == NULL) return 0; skb->len = sizeoftlvs; memcpy(skb->data, tlvs, sizeoftlvs); retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb); if (retval != 0) printk("lec.c: lane2_associate_req() failed\n"); /* If the previous association has changed we must * somehow notify other LANE entities about the change */ return (1);}/* * LANE2: 3.1.5, LE_ASSOCIATE.indication * */static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr, u8 *tlvs, u32 sizeoftlvs){#if 0 int i = 0;#endif struct lec_priv *priv = (struct lec_priv *)dev->priv;#if 0 /* Why have the TLVs in LE_ARP entries since we do not use them? When you uncomment this code, make sure the TLVs get freed when entry is killed */ struct lec_arp_table *entry = lec_arp_find(priv, mac_addr); if (entry == NULL) return; /* should not happen */ kfree(entry->tlvs); entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL); if (entry->tlvs == NULL) return; entry->sizeoftlvs = sizeoftlvs; memcpy(entry->tlvs, tlvs, sizeoftlvs);#endif#if 0 printk("lec.c: lane2_associate_ind()\n"); printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs); while (i < sizeoftlvs) printk("%02x ", tlvs[i++]); printk("\n");#endif /* tell MPOA about the TLVs we saw */ if (priv->lane2_ops && priv->lane2_ops->associate_indicator) { priv->lane2_ops->associate_indicator(dev, mac_addr, tlvs, sizeoftlvs); } return;}/* * Here starts what used to lec_arpc.c * * lec_arpc.c was added here when making * lane client modular. October 1997 * */#include <linux/types.h>#include <linux/sched.h>#include <linux/timer.h>#include <asm/param.h>#include <asm/atomic.h>#include <linux/inetdevice.h>#include <net/route.h>#if 0#define DPRINTK(format,args...)/*#define DPRINTK printk*/#endif#define DEBUG_ARP_TABLE 0#define LEC_ARP_REFRESH_INTERVAL (3*HZ)static void lec_arp_check_expire(unsigned long data);static void lec_arp_expire_arp(unsigned long data);void dump_arp_table(struct lec_priv *priv);/* * Arp table funcs */#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1))static __inline__ void lec_arp_get(struct lec_priv *priv){ atomic_inc(&priv->lec_arp_users);}static __inline__ void lec_arp_put(struct lec_priv *priv){ atomic_dec(&priv->lec_arp_users);}/* * Initialization of arp-cache */void lec_arp_init(struct lec_priv *priv){ unsigned short i; for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { priv->lec_arp_tables[i] = NULL; } spin_lock_init(&priv->lec_arp_lock); init_timer(&priv->lec_arp_timer); priv->lec_arp_timer.expires = jiffies+LEC_ARP_REFRESH_INTERVAL; priv->lec_arp_timer.data = (unsigned long)priv; priv->lec_arp_timer.function = lec_arp_check_expire; add_timer(&priv->lec_arp_timer);}voidlec_arp_clear_vccs(struct lec_arp_table *entry){ if (entry->vcc) { struct atm_vcc *vcc = entry->vcc; struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); struct net_device *dev = (struct net_device*) vcc->proto_data; vcc->pop = vpriv->old_pop; if (vpriv->xoff) netif_wake_queue(dev); kfree(vpriv); vcc->user_back = NULL; vcc->push = entry->old_push; vcc_release_async(vcc, -EPIPE); vcc = NULL; } if (entry->recv_vcc) { entry->recv_vcc->push = entry->old_recv_push; vcc_release_async(entry->recv_vcc, -EPIPE); entry->recv_vcc = NULL; } }/* * Insert entry to lec_arp_table * LANE2: Add to the end of the list to satisfy 8.1.13 */static inline void lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add){ unsigned long flags; unsigned short place; struct lec_arp_table *tmp; spin_lock_irqsave(&priv->lec_arp_lock, flags); place = HASH(to_add->mac_addr[ETH_ALEN-1]); tmp = priv->lec_arp_tables[place]; to_add->next = NULL; if (tmp == NULL) priv->lec_arp_tables[place] = to_add; else { /* add to the end */ while (tmp->next) tmp = tmp->next; tmp->next = to_add; } spin_unlock_irqrestore(&priv->lec_arp_lock, flags); DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1], 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3], 0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]);}/* * Remove entry from lec_arp_table */static int lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove){ unsigned long flags; unsigned short place; struct lec_arp_table *tmp; int remove_vcc=1; spin_lock_irqsave(&priv->lec_arp_lock, flags); if (!to_remove) { spin_unlock_irqrestore(&priv->lec_arp_lock, flags); return -1; } place = HASH(to_remove->mac_addr[ETH_ALEN-1]); tmp = priv->lec_arp_tables[place]; if (tmp == to_remove) { priv->lec_arp_tables[place] = tmp->next; } else { while(tmp && tmp->next != to_remove) { tmp = tmp->next; } if (!tmp) {/* Entry was not found */ spin_unlock_irqrestore(&priv->lec_arp_lock, flags); return -1; } } tmp->next = to_remove->next; del_timer(&to_remove->timer); /* If this is the only MAC connected to this VCC, also tear down the VCC */ if (to_remove->status >= ESI_FLUSH_PENDING) { /* * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT */ for(place=0;place<LEC_ARP_TABLE_SIZE;place++) { for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) { if (memcmp(tmp->atm_addr, to_remove->atm_addr, ATM_ESA_LEN)==0) { remove_vcc=0; break; } } } if (remove_vcc) lec_arp_clear_vccs(to_remove); } skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */ spin_unlock_irqrestore(&priv->lec_arp_lock, flags); DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1], 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3], 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]); return 0;}#if DEBUG_ARP_TABLEstatic char*get_status_string(unsigned char st){ switch(st) { case ESI_UNKNOWN: return "ESI_UNKNOWN"; case ESI_ARP_PENDING: return "ESI_ARP_PENDING"; case ESI_VC_PENDING: return "ESI_VC_PENDING"; case ESI_FLUSH_PENDING: return "ESI_FLUSH_PENDING"; case ESI_FORWARD_DIRECT: return "ESI_FORWARD_DIRECT"; default: return "<UNKNOWN>"; }}#endifvoiddump_arp_table(struct lec_priv *priv){#if DEBUG_ARP_TABLE int i,j, offset; struct lec_arp_table *rulla; char buf[1024]; struct lec_arp_table **lec_arp_tables = (struct lec_arp_table **)priv->lec_arp_tables; struct lec_arp_table *lec_arp_empty_ones = (struct lec_arp_table *)priv->lec_arp_empty_ones; struct lec_arp_table *lec_no_forward = (struct lec_arp_table *)priv->lec_no_forward; struct lec_arp_table *mcast_fwds = priv->mcast_fwds; printk("Dump %p:\n",priv); for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { rulla = lec_arp_tables[i]; offset = 0; offset += sprintf(buf,"%d: %p\n",i, rulla); while (rulla) { offset += sprintf(buf+offset,"Mac:"); for(j=0;j<ETH_ALEN;j++) { offset+=sprintf(buf+offset, "%2.2x ", rulla->mac_addr[j]&0xff); } offset +=sprintf(buf+offset,"Atm:"); for(j=0;j<ATM_ESA_LEN;j++) { offset+=sprintf(buf+offset, "%2.2x ", rulla->atm_addr[j]&0xff); } offset+=sprintf(buf+offset, "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", rulla->vcc?rulla->vcc->vpi:0, rulla->vcc?rulla->vcc->vci:0, rulla->recv_vcc?rulla->recv_vcc->vpi:0, rulla->recv_vcc?rulla->recv_vcc->vci:0, rulla->last_used, rulla->timestamp, rulla->no_tries); offset+=sprintf(buf+offset, "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -