📄 lec.c
字号:
lec_vcc_attach(struct atm_vcc *vcc, void *arg){ int bytes_left; struct atmlec_ioc ioc_data; /* Lecd must be up in this case */ bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); if (bytes_left != 0) { printk("lec: lec_vcc_attach, copy from user failed for %d bytes\n", bytes_left); } if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || !dev_lec[ioc_data.dev_num]) return -EINVAL; lec_vcc_added(dev_lec[ioc_data.dev_num]->priv, &ioc_data, vcc, vcc->push); vcc->push = lec_push; vcc->proto_data = dev_lec[ioc_data.dev_num]; return 0;}int lec_mcast_attach(struct atm_vcc *vcc, int arg){ if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg]) return -EINVAL; vcc->proto_data = dev_lec[arg]; return (lec_mcast_make((struct lec_priv*)dev_lec[arg]->priv, vcc));}/* Initialize device. */int lecd_attach(struct atm_vcc *vcc, int arg){ int i; struct lec_priv *priv; if (arg<0) i = 0; else i = arg;#ifdef CONFIG_TR if (arg >= MAX_LEC_ITF) return -EINVAL;#else /* Reserve the top NUM_TR_DEVS for TR */ if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS)) return -EINVAL;#endif if (!dev_lec[i]) { int is_trdev, size; is_trdev = 0; if (i >= (MAX_LEC_ITF - NUM_TR_DEVS)) is_trdev = 1; size = sizeof(struct lec_priv);#ifdef CONFIG_TR if (is_trdev) dev_lec[i] = init_trdev(NULL, size); else#endif dev_lec[i] = init_etherdev(NULL, size); if (!dev_lec[i]) return -ENOMEM; priv = dev_lec[i]->priv; priv->is_trdev = is_trdev; sprintf(dev_lec[i]->name, "lec%d", i); lec_init(dev_lec[i]); } else { priv = dev_lec[i]->priv; if (priv->lecd) return -EADDRINUSE; } lec_arp_init(priv); priv->itfnum = i; /* LANE2 addition */ priv->lecd = vcc; bind_vcc(vcc, &lecatm_dev); vcc->proto_data = dev_lec[i]; set_bit(ATM_VF_META,&vcc->flags); set_bit(ATM_VF_READY,&vcc->flags); /* Set default values to these variables */ priv->maximum_unknown_frame_count = 1; priv->max_unknown_frame_time = (1*HZ); priv->vcc_timeout_period = (1200*HZ); priv->max_retry_count = 1; priv->aging_time = (300*HZ); priv->forward_delay_time = (15*HZ); priv->topology_change = 0; priv->arp_response_time = (1*HZ); priv->flush_timeout = (4*HZ); priv->path_switching_delay = (6*HZ); if (dev_lec[i]->flags & IFF_UP) { netif_start_queue(dev_lec[i]); } MOD_INC_USE_COUNT; return i;}void atm_lane_init_ops(struct atm_lane_ops *ops){ ops->lecd_attach = lecd_attach; ops->mcast_attach = lec_mcast_attach; ops->vcc_attach = lec_vcc_attach; ops->get_lecs = get_dev_lec; printk("lec.c: " __DATE__ " " __TIME__ " initialized\n"); return;}static int __init lane_module_init(void){ extern struct atm_lane_ops atm_lane_ops; atm_lane_init_ops(&atm_lane_ops); return 0;}static void __exit lane_module_cleanup(void){ int i; extern struct atm_lane_ops atm_lane_ops; struct lec_priv *priv; atm_lane_ops.lecd_attach = NULL; atm_lane_ops.mcast_attach = NULL; atm_lane_ops.vcc_attach = NULL; atm_lane_ops.get_lecs = NULL; for (i = 0; i < MAX_LEC_ITF; i++) { if (dev_lec[i] != NULL) { priv = (struct lec_priv *)dev_lec[i]->priv;#if defined(CONFIG_TR) if (priv->is_trdev) unregister_trdev(dev_lec[i]); else#endif unregister_netdev(dev_lec[i]); kfree(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 __inline__ 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_lock(struct lec_priv *priv){ atomic_inc(&priv->lec_arp_lock_var);}static __inline__ void lec_arp_unlock(struct lec_priv *priv){ atomic_dec(&priv->lec_arp_lock_var);}/* * 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; } 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) { entry->vcc->push = entry->old_push;#if 0 /* August 6, 1998 */ set_bit(ATM_VF_RELEASED,&entry->vcc->flags); clear_bit(ATM_VF_READY,&entry->vcc->flags); entry->vcc->push(entry->vcc, NULL);#endif atm_async_release_vcc(entry->vcc, -EPIPE); entry->vcc = NULL; } if (entry->recv_vcc) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -