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

📄 lec.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (mesg->content.normal.no_source_le_narp)			break;		/* FALL THROUGH */	case l_arp_update:		lec_arp_update(priv, mesg->content.normal.mac_addr,			       mesg->content.normal.atm_addr,			       mesg->content.normal.flag,			       mesg->content.normal.targetless_le_arp);		pr_debug("lec: in l_arp_update\n");		if (mesg->sizeoftlvs != 0) {	/* LANE2 3.1.5 */			pr_debug("lec: LANE2 3.1.5, got tlvs, size %d\n",				mesg->sizeoftlvs);			lane2_associate_ind(dev, mesg->content.normal.mac_addr,					    tmp, mesg->sizeoftlvs);		}		break;	case l_config:		priv->maximum_unknown_frame_count =		    mesg->content.config.maximum_unknown_frame_count;		priv->max_unknown_frame_time =		    (mesg->content.config.max_unknown_frame_time * HZ);		priv->max_retry_count = mesg->content.config.max_retry_count;		priv->aging_time = (mesg->content.config.aging_time * HZ);		priv->forward_delay_time =		    (mesg->content.config.forward_delay_time * HZ);		priv->arp_response_time =		    (mesg->content.config.arp_response_time * HZ);		priv->flush_timeout = (mesg->content.config.flush_timeout * HZ);		priv->path_switching_delay =		    (mesg->content.config.path_switching_delay * HZ);		priv->lane_version = mesg->content.config.lane_version;	/* LANE2 */		priv->lane2_ops = NULL;		if (priv->lane_version > 1)			priv->lane2_ops = &lane2_ops;		if (dev->change_mtu(dev, mesg->content.config.mtu))			printk("%s: change_mtu to %d failed\n", dev->name,			       mesg->content.config.mtu);		priv->is_proxy = mesg->content.config.is_proxy;		break;	case l_flush_tran_id:		lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,				      mesg->content.normal.flag);		break;	case l_set_lecid:		priv->lecid =		    (unsigned short)(0xffff & mesg->content.normal.flag);		break;	case l_should_bridge:#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)		{			struct net_bridge_fdb_entry *f;			pr_debug			    ("%s: bridge zeppelin asks about %s\n",			     dev->name,			     print_mac(mac, mesg->content.proxy.mac_addr));			if (br_fdb_get_hook == NULL || dev->br_port == NULL)				break;			f = br_fdb_get_hook(dev->br_port->br,					    mesg->content.proxy.mac_addr);			if (f != NULL && f->dst->dev != dev			    && f->dst->state == BR_STATE_FORWARDING) {				/* hit from bridge table, send LE_ARP_RESPONSE */				struct sk_buff *skb2;				struct sock *sk;				pr_debug				    ("%s: entry found, responding to zeppelin\n",				     dev->name);				skb2 =				    alloc_skb(sizeof(struct atmlec_msg),					      GFP_ATOMIC);				if (skb2 == NULL) {					br_fdb_put_hook(f);					break;				}				skb2->len = sizeof(struct atmlec_msg);				skb_copy_to_linear_data(skb2, mesg,							sizeof(*mesg));				atm_force_charge(priv->lecd, skb2->truesize);				sk = sk_atm(priv->lecd);				skb_queue_tail(&sk->sk_receive_queue, skb2);				sk->sk_data_ready(sk, skb2->len);			}			if (f != NULL)				br_fdb_put_hook(f);		}#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */		break;	default:		printk("%s: Unknown message type %d\n", dev->name, mesg->type);		dev_kfree_skb(skb);		return -EINVAL;	}	dev_kfree_skb(skb);	return 0;}static void lec_atm_close(struct atm_vcc *vcc){	struct sk_buff *skb;	struct net_device *dev = (struct net_device *)vcc->proto_data;	struct lec_priv *priv = (struct lec_priv *)dev->priv;	priv->lecd = NULL;	/* Do something needful? */	netif_stop_queue(dev);	lec_arp_destroy(priv);	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))		printk("%s lec_atm_close: closing with messages pending\n",		       dev->name);	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {		atm_return(vcc, skb->truesize);		dev_kfree_skb(skb);	}	printk("%s: Shut down!\n", dev->name);	module_put(THIS_MODULE);}static struct atmdev_ops lecdev_ops = {	.close = lec_atm_close,	.send = lec_atm_send};static struct atm_dev lecatm_dev = {	.ops = &lecdev_ops,	.type = "lec",	.number = 999,		/* dummy device number */	.lock = __SPIN_LOCK_UNLOCKED(lecatm_dev.lock)};/* * LANE2: new argument struct sk_buff *data contains * the LE_ARP based TLVs introduced in the LANE2 spec */static intsend_to_lecd(struct lec_priv *priv, atmlec_msg_type type,	     unsigned char *mac_addr, unsigned char *atm_addr,	     struct sk_buff *data){	struct sock *sk;	struct sk_buff *skb;	struct atmlec_msg *mesg;	if (!priv || !priv->lecd) {		return -1;	}	skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);	if (!skb)		return -1;	skb->len = sizeof(struct atmlec_msg);	mesg = (struct atmlec_msg *)skb->data;	memset(mesg, 0, sizeof(struct atmlec_msg));	mesg->type = type;	if (data != NULL)		mesg->sizeoftlvs = data->len;	if (mac_addr)		memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);	else		mesg->content.normal.targetless_le_arp = 1;	if (atm_addr)		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);	atm_force_charge(priv->lecd, skb->truesize);	sk = sk_atm(priv->lecd);	skb_queue_tail(&sk->sk_receive_queue, skb);	sk->sk_data_ready(sk, skb->len);	if (data != NULL) {		pr_debug("lec: about to send %d bytes of data\n", data->len);		atm_force_charge(priv->lecd, data->truesize);		skb_queue_tail(&sk->sk_receive_queue, data);		sk->sk_data_ready(sk, skb->len);	}	return 0;}/* shamelessly stolen from drivers/net/net_init.c */static int lec_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < 68) || (new_mtu > 18190))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static void lec_set_multicast_list(struct net_device *dev){	/*	 * by default, all multicast frames arrive over the bus.	 * eventually support selective multicast service	 */	return;}static void lec_init(struct net_device *dev){	dev->change_mtu = lec_change_mtu;	dev->open = lec_open;	dev->stop = lec_close;	dev->hard_start_xmit = lec_start_xmit;	dev->tx_timeout = lec_tx_timeout;	dev->get_stats = lec_get_stats;	dev->set_multicast_list = lec_set_multicast_list;	dev->do_ioctl = NULL;	printk("%s: Initialized!\n", dev->name);	return;}static unsigned char lec_ctrl_magic[] = {	0xff,	0x00,	0x01,	0x01};#define LEC_DATA_DIRECT_8023  2#define LEC_DATA_DIRECT_8025  3static int lec_is_data_direct(struct atm_vcc *vcc){	return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||		(vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));}static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb){	unsigned long flags;	struct net_device *dev = (struct net_device *)vcc->proto_data;	struct lec_priv *priv = (struct lec_priv *)dev->priv;#if DUMP_PACKETS >0	int i = 0;	char buf[300];	printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,	       vcc->vpi, vcc->vci);#endif	if (!skb) {		pr_debug("%s: null skb\n", dev->name);		lec_vcc_close(priv, vcc);		return;	}#if DUMP_PACKETS > 0	printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,	       skb->len, priv->lecid);#if DUMP_PACKETS >= 2	for (i = 0; i < skb->len && i < 99; i++) {		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);	}#elif DUMP_PACKETS >= 1	for (i = 0; i < skb->len && i < 30; i++) {		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);	}#endif /* DUMP_PACKETS >= 1 */	if (i == skb->len)		printk("%s\n", buf);	else		printk("%s...\n", buf);#endif /* DUMP_PACKETS > 0 */	if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {	/* Control frame, to daemon */		struct sock *sk = sk_atm(vcc);		pr_debug("%s: To daemon\n", dev->name);		skb_queue_tail(&sk->sk_receive_queue, skb);		sk->sk_data_ready(sk, skb->len);	} else {		/* Data frame, queue to protocol handlers */		struct lec_arp_table *entry;		unsigned char *src, *dst;		atm_return(vcc, skb->truesize);		if (*(__be16 *) skb->data == htons(priv->lecid) ||		    !priv->lecd || !(dev->flags & IFF_UP)) {			/*			 * Probably looping back, or if lecd is missing,			 * lecd has gone down			 */			pr_debug("Ignoring frame...\n");			dev_kfree_skb(skb);			return;		}#ifdef CONFIG_TR		if (priv->is_trdev)			dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;		else#endif			dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;		/*		 * If this is a Data Direct VCC, and the VCC does not match		 * the LE_ARP cache entry, delete the LE_ARP cache entry.		 */		spin_lock_irqsave(&priv->lec_arp_lock, flags);		if (lec_is_data_direct(vcc)) {#ifdef CONFIG_TR			if (priv->is_trdev)				src =				    ((struct lecdatahdr_8025 *)skb->data)->				    h_source;			else#endif				src =				    ((struct lecdatahdr_8023 *)skb->data)->				    h_source;			entry = lec_arp_find(priv, src);			if (entry && entry->vcc != vcc) {				lec_arp_remove(priv, entry);				lec_arp_put(entry);			}		}		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);		if (!(dst[0] & 0x01) &&	/* Never filter Multi/Broadcast */		    !priv->is_proxy &&	/* Proxy wants all the packets */		    memcmp(dst, dev->dev_addr, dev->addr_len)) {			dev_kfree_skb(skb);			return;		}		if (!hlist_empty(&priv->lec_arp_empty_ones)) {			lec_arp_check_empties(priv, vcc, skb);		}		skb_pull(skb, 2);	/* skip lec_id */#ifdef CONFIG_TR		if (priv->is_trdev)			skb->protocol = tr_type_trans(skb, dev);		else#endif			skb->protocol = eth_type_trans(skb, dev);		priv->stats.rx_packets++;		priv->stats.rx_bytes += skb->len;		memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));		netif_rx(skb);	}}static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb){	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);	struct net_device *dev = skb->dev;	if (vpriv == NULL) {		printk("lec_pop(): vpriv = NULL!?!?!?\n");		return;	}	vpriv->old_pop(vcc, skb);	if (vpriv->xoff && atm_may_send(vcc, 0)) {		vpriv->xoff = 0;		if (netif_running(dev) && netif_queue_stopped(dev))			netif_wake_queue(dev);	}}static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg){	struct lec_vcc_priv *vpriv;	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;	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;	lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,		      &ioc_data, vcc, vcc->push);	vcc->proto_data = dev_lec[ioc_data.dev_num];	vcc->push = lec_push;	return 0;}static 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. */static 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] = alloc_trdev(size);		else#endif			dev_lec[i] = alloc_etherdev(size);		if (!dev_lec[i])			return -ENOMEM;		snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);		if (register_netdev(dev_lec[i])) {			free_netdev(dev_lec[i]);			return -EINVAL;		}		priv = dev_lec[i]->priv;		priv->is_trdev = is_trdev;		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;	vcc->dev = &lecatm_dev;	vcc_insert_socket(sk_atm(vcc));	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]);	}	__module_get(THIS_MODULE);	return i;}#ifdef CONFIG_PROC_FSstatic char *lec_arp_get_status_string(unsigned char status){	static char *lec_arp_status_string[] = {		"ESI_UNKNOWN       ",		"ESI_ARP_PENDING   ",		"ESI_VC_PENDING    ",		"<Undefined>       ",		"ESI_FLUSH_PENDING ",

⌨️ 快捷键说明

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