⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lec.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,				       unsigned char *mac_to_find, int is_rdesc,				       struct lec_arp_table **ret_entry){	unsigned long flags;	struct lec_arp_table *entry;	struct atm_vcc *found;	if (mac_to_find[0] & 0x01) {		switch (priv->lane_version) {		case 1:			return priv->mcast_vcc;			break;		case 2:	/* LANE2 wants arp for multicast addresses */			if (!compare_ether_addr(mac_to_find, bus_mac))				return priv->mcast_vcc;			break;		default:			break;		}	}	spin_lock_irqsave(&priv->lec_arp_lock, flags);	entry = lec_arp_find(priv, mac_to_find);	if (entry) {		if (entry->status == ESI_FORWARD_DIRECT) {			/* Connection Ok */			entry->last_used = jiffies;			lec_arp_hold(entry);			*ret_entry = entry;			found = entry->vcc;			goto out;		}		/*		 * If the LE_ARP cache entry is still pending, reset count to 0		 * so another LE_ARP request can be made for this frame.		 */		if (entry->status == ESI_ARP_PENDING) {			entry->no_tries = 0;		}		/*		 * Data direct VC not yet set up, check to see if the unknown		 * frame count is greater than the limit. If the limit has		 * not been reached, allow the caller to send packet to		 * BUS.		 */		if (entry->status != ESI_FLUSH_PENDING &&		    entry->packets_flooded <		    priv->maximum_unknown_frame_count) {			entry->packets_flooded++;			pr_debug("LEC_ARP: Flooding..\n");			found = priv->mcast_vcc;			goto out;		}		/*		 * We got here because entry->status == ESI_FLUSH_PENDING		 * or BUS flood limit was reached for an entry which is		 * in ESI_ARP_PENDING or ESI_VC_PENDING state.		 */		lec_arp_hold(entry);		*ret_entry = entry;		pr_debug("lec: entry->status %d entry->vcc %p\n", entry->status,			entry->vcc);		found = NULL;	} else {		/* No matching entry was found */		entry = make_entry(priv, mac_to_find);		pr_debug("LEC_ARP: Making entry\n");		if (!entry) {			found = priv->mcast_vcc;			goto out;		}		lec_arp_add(priv, entry);		/* We want arp-request(s) to be sent */		entry->packets_flooded = 1;		entry->status = ESI_ARP_PENDING;		entry->no_tries = 1;		entry->last_used = entry->timestamp = jiffies;		entry->is_rdesc = is_rdesc;		if (entry->is_rdesc)			send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL,				     NULL);		else			send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);		entry->timer.expires = jiffies + (1 * HZ);		entry->timer.function = lec_arp_expire_arp;		add_timer(&entry->timer);		found = priv->mcast_vcc;	}out:	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);	return found;}static intlec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,		unsigned long permanent){	unsigned long flags;	struct hlist_node *node, *next;	struct lec_arp_table *entry;	int i;	pr_debug("lec_addr_delete\n");	spin_lock_irqsave(&priv->lec_arp_lock, flags);	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)			    && (permanent ||				!(entry->flags & LEC_PERMANENT_FLAG))) {				lec_arp_remove(priv, entry);				lec_arp_put(entry);			}			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);			return 0;		}	}	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);	return -1;}/* * Notifies:  Response to arp_request (atm_addr != NULL) */static voidlec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,	       unsigned char *atm_addr, unsigned long remoteflag,	       unsigned int targetless_le_arp){	unsigned long flags;	struct hlist_node *node, *next;	struct lec_arp_table *entry, *tmp;	int i;	pr_debug("lec:%s", (targetless_le_arp) ? "targetless " : " ");	pr_debug("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",		mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],		mac_addr[4], mac_addr[5]);	spin_lock_irqsave(&priv->lec_arp_lock, flags);	entry = lec_arp_find(priv, mac_addr);	if (entry == NULL && targetless_le_arp)		goto out;	/*				 * LANE2: ignore targetless LE_ARPs for which				 * we have no entry in the cache. 7.1.30				 */	if (!hlist_empty(&priv->lec_arp_empty_ones)) {		hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {			if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {				hlist_del(&entry->next);				del_timer(&entry->timer);				tmp = lec_arp_find(priv, mac_addr);				if (tmp) {					del_timer(&tmp->timer);					tmp->status = ESI_FORWARD_DIRECT;					memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);					tmp->vcc = entry->vcc;					tmp->old_push = entry->old_push;					tmp->last_used = jiffies;					del_timer(&entry->timer);					lec_arp_put(entry);					entry = tmp;				} else {					entry->status = ESI_FORWARD_DIRECT;					memcpy(entry->mac_addr, mac_addr, ETH_ALEN);					entry->last_used = jiffies;					lec_arp_add(priv, entry);				}				if (remoteflag)					entry->flags |= LEC_REMOTE_FLAG;				else					entry->flags &= ~LEC_REMOTE_FLAG;				pr_debug("After update\n");				dump_arp_table(priv);				goto out;			}		}	}	entry = lec_arp_find(priv, mac_addr);	if (!entry) {		entry = make_entry(priv, mac_addr);		if (!entry)			goto out;		entry->status = ESI_UNKNOWN;		lec_arp_add(priv, entry);		/* Temporary, changes before end of function */	}	memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);	del_timer(&entry->timer);	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {		hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) {			if (entry != tmp &&			    !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {				/* Vcc to this host exists */				if (tmp->status > ESI_VC_PENDING) {					/*					 * ESI_FLUSH_PENDING,					 * ESI_FORWARD_DIRECT					 */					entry->vcc = tmp->vcc;					entry->old_push = tmp->old_push;				}				entry->status = tmp->status;				break;			}		}	}	if (remoteflag)		entry->flags |= LEC_REMOTE_FLAG;	else		entry->flags &= ~LEC_REMOTE_FLAG;	if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {		entry->status = ESI_VC_PENDING;		send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);	}	pr_debug("After update2\n");	dump_arp_table(priv);out:	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);}/* * Notifies: Vcc setup ready */static voidlec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,	      struct atm_vcc *vcc,	      void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb)){	unsigned long flags;	struct hlist_node *node;	struct lec_arp_table *entry;	int i, found_entry = 0;	spin_lock_irqsave(&priv->lec_arp_lock, flags);	if (ioc_data->receive == 2) {		/* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */		pr_debug("LEC_ARP: Attaching mcast forward\n");#if 0		entry = lec_arp_find(priv, bus_mac);		if (!entry) {			printk("LEC_ARP: Multicast entry not found!\n");			goto out;		}		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);		entry->recv_vcc = vcc;		entry->old_recv_push = old_push;#endif		entry = make_entry(priv, bus_mac);		if (entry == NULL)			goto out;		del_timer(&entry->timer);		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);		entry->recv_vcc = vcc;		entry->old_recv_push = old_push;		hlist_add_head(&entry->next, &priv->mcast_fwds);		goto out;	} else if (ioc_data->receive == 1) {		/*		 * Vcc which we don't want to make default vcc,		 * attach it anyway.		 */		pr_debug		    ("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",		     ioc_data->atm_addr[0], ioc_data->atm_addr[1],		     ioc_data->atm_addr[2], ioc_data->atm_addr[3],		     ioc_data->atm_addr[4], ioc_data->atm_addr[5],		     ioc_data->atm_addr[6], ioc_data->atm_addr[7],		     ioc_data->atm_addr[8], ioc_data->atm_addr[9],		     ioc_data->atm_addr[10], ioc_data->atm_addr[11],		     ioc_data->atm_addr[12], ioc_data->atm_addr[13],		     ioc_data->atm_addr[14], ioc_data->atm_addr[15],		     ioc_data->atm_addr[16], ioc_data->atm_addr[17],		     ioc_data->atm_addr[18], ioc_data->atm_addr[19]);		entry = make_entry(priv, bus_mac);		if (entry == NULL)			goto out;		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);		memset(entry->mac_addr, 0, ETH_ALEN);		entry->recv_vcc = vcc;		entry->old_recv_push = old_push;		entry->status = ESI_UNKNOWN;		entry->timer.expires = jiffies + priv->vcc_timeout_period;		entry->timer.function = lec_arp_expire_vcc;		hlist_add_head(&entry->next, &priv->lec_no_forward);		add_timer(&entry->timer);		dump_arp_table(priv);		goto out;	}	pr_debug	    ("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",	     ioc_data->atm_addr[0], ioc_data->atm_addr[1],	     ioc_data->atm_addr[2], ioc_data->atm_addr[3],	     ioc_data->atm_addr[4], ioc_data->atm_addr[5],	     ioc_data->atm_addr[6], ioc_data->atm_addr[7],	     ioc_data->atm_addr[8], ioc_data->atm_addr[9],	     ioc_data->atm_addr[10], ioc_data->atm_addr[11],	     ioc_data->atm_addr[12], ioc_data->atm_addr[13],	     ioc_data->atm_addr[14], ioc_data->atm_addr[15],	     ioc_data->atm_addr[16], ioc_data->atm_addr[17],	     ioc_data->atm_addr[18], ioc_data->atm_addr[19]);	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {			if (memcmp			    (ioc_data->atm_addr, entry->atm_addr,			     ATM_ESA_LEN) == 0) {				pr_debug("LEC_ARP: Attaching data direct\n");				pr_debug("Currently -> Vcc: %d, Rvcc:%d\n",					entry->vcc ? entry->vcc->vci : 0,					entry->recv_vcc ? entry->recv_vcc->					vci : 0);				found_entry = 1;				del_timer(&entry->timer);				entry->vcc = vcc;				entry->old_push = old_push;				if (entry->status == ESI_VC_PENDING) {					if (priv->maximum_unknown_frame_count					    == 0)						entry->status =						    ESI_FORWARD_DIRECT;					else {						entry->timestamp = jiffies;						entry->status =						    ESI_FLUSH_PENDING;#if 0						send_to_lecd(priv, l_flush_xmt,							     NULL,							     entry->atm_addr,							     NULL);#endif					}				} else {					/*					 * They were forming a connection					 * to us, and we to them. Our					 * ATM address is numerically lower					 * than theirs, so we make connection					 * we formed into default VCC (8.1.11).					 * Connection they made gets torn					 * down. This might confuse some					 * clients. Can be changed if					 * someone reports trouble...					 */					;				}			}		}	}	if (found_entry) {		pr_debug("After vcc was added\n");		dump_arp_table(priv);		goto out;	}	/*	 * Not found, snatch address from first data packet that arrives	 * from this vcc	 */	entry = make_entry(priv, bus_mac);	if (!entry)		goto out;	entry->vcc = vcc;	entry->old_push = old_push;	memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);	memset(entry->mac_addr, 0, ETH_ALEN);	entry->status = ESI_UNKNOWN;	hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);	entry->timer.expires = jiffies + priv->vcc_timeout_period;	entry->timer.function = lec_arp_expire_vcc;	add_timer(&entry->timer);	pr_debug("After vcc was added\n");	dump_arp_table(priv);out:	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);}static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id){	unsigned long flags;	struct hlist_node *node;	struct lec_arp_table *entry;	int i;	pr_debug("LEC:lec_flush_complete %lx\n", tran_id);restart:	spin_lock_irqsave(&priv->lec_arp_lock, flags);	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {			if (entry->flush_tran_id == tran_id			    && entry->status == ESI_FLUSH_PENDING) {				struct sk_buff *skb;				struct atm_vcc *vcc = entry->vcc;				lec_arp_hold(entry);				spin_unlock_irqrestore(&priv->lec_arp_lock, flags);				while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)					lec_send(vcc, skb, entry->priv);				entry->last_used = jiffies;				entry->status = ESI_FORWARD_DIRECT;				lec_arp_put(entry);				pr_debug("LEC_ARP: Flushed\n");				goto restart;			}		}	}	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);	dump_arp_table(priv);}static voidlec_set_flush_tran_id(struct lec_priv *priv,		      unsigned char *atm_addr, unsigned long tran_id){	unsigned long flags;	struct hlist_node *node;	struct lec_arp_table *entry;	int i;	spin_lock_irqsave(&priv->lec_arp_lock, flags);	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)		hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {				entry->flush_tran_id = tran_id;				pr_debug("Set flush transaction id to %lx for %p\n",					tran_id, entry);			}		}	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);}static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc){	unsigned long flags;	unsigned char mac_addr[] = {		0xff, 0xff, 0xff, 0xff, 0xff, 0xff	};	struct lec_arp_table *to_add;	struct lec_vcc_priv *vpriv;	int err = 0;	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))		return -ENOMEM;	vpriv->xoff = 0;	vpriv->old_pop = vcc->pop;	vcc->user_back = vpriv;	vcc->pop = lec_pop;	spin_lock_irqsave(&priv->lec_arp_lock, flags);	to_add = make_entry(priv, mac_addr);	if (!to_add) {		vcc->pop = vpriv->old_pop;		kfree(vpriv);		err = -ENOMEM;		goto out;	}	memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);	to_add->status = ESI_FORWARD_DIRECT;	to_add->flags |= LEC_PERMANENT_FLAG;	to_add->vcc = vcc;	to_add->old_push = vcc->push;	vcc->push = lec_push;	priv->mcast_vcc = vcc;	lec_arp_add(priv, to_add);out:	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);	return err;}static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc){	unsigned long flags;	struct hlist_node *node, *next;	struct lec_arp_table *entry;	int i;	pr_debug("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);	du

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -