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

📄 comx-proto-fr.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		newskb->dev=fr->master;		dev_queue_xmit(newskb);		ch->stats.tx_bytes += skb->len;		ch->stats.tx_packets++;		dev_kfree_skb(skb);	} else {		netif_stop_queue(dev);		for (; dir ; dir = dir->next) {			if(!S_ISDIR(dir->mode)) {			    continue;			}			if ((sdev = dir->data) && (sch = sdev->priv) && 			    (sdev->type == ARPHRD_DLCI) && (sfr = sch->LINE_privdata) &&			    (sfr->master == dev) && (netif_queue_stopped(sdev))) {				netif_stop_queue(sdev);			}		}		 			switch(mch->HW_send_packet(dev, skb)) {			case FRAME_QUEUED:				netif_wake_queue(dev);				break;			case FRAME_ACCEPTED:			case FRAME_DROPPED:				break;			case FRAME_ERROR:				printk(KERN_ERR "%s: Transmit frame error (len %d)\n", 					dev->name, skb->len);				break;		}	}	return 0;}static int fr_header(struct sk_buff *skb, struct net_device *dev, 	unsigned short type, void *daddr, void *saddr, unsigned len) {	struct comx_channel *ch = dev->priv;	struct fr_data *fr = ch->LINE_privdata;	skb_push(skb, dev->hard_header_len);	  	/* Put in DLCI */	skb->data[0] = (fr->dlci & (1024 - 15)) >> 2;	skb->data[1] = (fr->dlci & 15) << 4 | 1;	// EA bit 1	skb->data[2] = FRAD_UI;	skb->data[3] = NLPID_IP;	return dev->hard_header_len;  }static int fr_statistics(struct net_device *dev, char *page) {	struct comx_channel *ch = dev->priv;	struct fr_data *fr = ch->LINE_privdata;	int len = 0;	if (fr->master == dev) {		struct proc_dir_entry *dir = ch->procdir->parent->subdir;		struct net_device *sdev;		struct comx_channel *sch;		struct fr_data *sfr;		int slaves = 0;		len += sprintf(page + len, 			"This is a Frame Relay master device\nSlaves: ");		for (; dir ; dir = dir->next) {			if(!S_ISDIR(dir->mode)) {				continue;			}			if ((sdev = dir->data) && (sch = sdev->priv) && 			    (sdev->type == ARPHRD_DLCI) &&			    (sfr = sch->LINE_privdata) && 			    (sfr->master == dev) && (sdev != dev)) {				slaves++;				len += sprintf(page + len, "%s ", sdev->name);			}		}		len += sprintf(page + len, "%s\n", slaves ? "" : "(none)");		if (fr->keepa_freq) {			len += sprintf(page + len, "Line keepalive (value %d) "				"status %s [%d]\n", fr->keepa_freq, 				ch->line_status & PROTO_LOOP ? "LOOP" :				ch->line_status & PROTO_UP ? "UP" : "DOWN", 				fr->keepalivecnt);		} else {			len += sprintf(page + len, "Line keepalive protocol "				"is not set\n");		}	} else {		// if slave		len += sprintf(page + len, 			"This is a Frame Relay slave device, master: %s\n",			fr->master ? fr->master->name : "(not set)");	}	return len;}static int fr_read_proc(char *page, char **start, off_t off, int count,	int *eof, void *data){	struct proc_dir_entry *file = (struct proc_dir_entry *)data;	struct net_device *dev = file->parent->data;	struct comx_channel *ch = dev->priv;	struct fr_data *fr = NULL;	int len = 0;	if (ch) {		fr = ch->LINE_privdata;	}	if (strcmp(file->name, FILENAME_DLCI) == 0) {		len = sprintf(page, "%04d\n", fr->dlci);	} else if (strcmp(file->name, FILENAME_MASTER) == 0) {		len = sprintf(page, "%-9s\n", fr->master ? fr->master->name :			"(none)");	} else if (strcmp(file->name, FILENAME_KEEPALIVE) == 0) {		len = fr->keepa_freq ? sprintf(page, "% 3d\n", fr->keepa_freq) 			: sprintf(page, "off\n");	} else {		printk(KERN_ERR "comxfr: internal error, filename %s\n", file->name);		return -EBADF;	}	if (off >= len) {		*eof = 1;		return 0;	}	*start = page + off;	if (count >= len - off) *eof = 1;	return min_t(int, count, len - off);}static int fr_write_proc(struct file *file, const char *buffer, 	u_long count, void *data){	struct proc_dir_entry *entry = (struct proc_dir_entry *)data;	struct net_device *dev = entry->parent->data;	struct comx_channel *ch = dev->priv;	struct fr_data *fr = NULL; 	char *page;	if (ch) {		fr = ch->LINE_privdata;	}	if (!(page = (char *)__get_free_page(GFP_KERNEL))) {		return -ENOMEM;	}	copy_from_user(page, buffer, count);	if (*(page + count - 1) == '\n') {		*(page + count - 1) = 0;	}	if (strcmp(entry->name, FILENAME_DLCI) == 0) {		u16 dlci_new = simple_strtoul(page, NULL, 10);		if (dlci_new > 1023) {			printk(KERN_ERR "Invalid DLCI value\n");		}		else fr->dlci = dlci_new;	} else if (strcmp(entry->name, FILENAME_MASTER) == 0) {		struct net_device *new_master = dev_get_by_name(page);		if (new_master && new_master->type == ARPHRD_FRAD) {			struct comx_channel *sch = new_master->priv;			struct fr_data *sfr = sch->LINE_privdata;			if (sfr && sfr->master == new_master) {				if(fr->master)					dev_put(fr->master);				fr->master = new_master;				/* Megorokli a master statuszat */				ch->line_status = sch->line_status;			}		}	} else if (strcmp(entry->name, FILENAME_KEEPALIVE) == 0) {		int keepa_new = -1;		if (strcmp(page, KEEPALIVE_OFF) == 0) {			keepa_new = 0;		} else {			keepa_new = simple_strtoul(page, NULL, 10);		}		if (keepa_new < 0 || keepa_new > 100) {			printk(KERN_ERR "invalid keepalive\n");		} else {			if (fr->keepa_freq && keepa_new != fr->keepa_freq) {				fr_set_keepalive(dev, 0);			}			if (keepa_new) {				fr_set_keepalive(dev, keepa_new);			}		}	} else {		printk(KERN_ERR "comxfr_write_proc: internal error, filename %s\n", 			entry->name);		count = -EBADF;	}	free_page((unsigned long)page);	return count;}static int fr_exit(struct net_device *dev) {	struct comx_channel *ch = dev->priv;	struct fr_data *fr = ch->LINE_privdata;	struct net_device *sdev = dev;	struct comx_channel *sch;	struct fr_data *sfr;	struct proc_dir_entry *dir = ch->procdir->parent->subdir;	/* Ha lezarunk egy master-t, le kell kattintani a slave-eket is */	if (fr->master && fr->master == dev) {		for (; dir ; dir = dir->next) {			if(!S_ISDIR(dir->mode)) {				continue;			}			if ((sdev = dir->data) && (sch = sdev->priv) && 			    (sdev->type == ARPHRD_DLCI) && 			    (sfr = sch->LINE_privdata) && (sfr->master == dev)) {				dev_close(sdev);				sfr->master = NULL;			}		}	}	dev->flags		= 0;	dev->type		= 0;	dev->mtu		= 0;	dev->hard_header_len    = 0;	ch->LINE_rx	= NULL;	ch->LINE_tx	= NULL;	ch->LINE_status = NULL;	ch->LINE_open	= NULL;	ch->LINE_close	= NULL;	ch->LINE_xmit	= NULL;	ch->LINE_header	= NULL;	ch->LINE_rebuild_header	= NULL;	ch->LINE_statistics = NULL;	ch->LINE_status = 0;	if (fr->master != dev) { // if not master, remove dlci		if(fr->master)			dev_put(fr->master);		remove_proc_entry(FILENAME_DLCI, ch->procdir);		remove_proc_entry(FILENAME_MASTER, ch->procdir);	} else {		if (fr->keepa_freq) {			fr_set_keepalive(dev, 0);		}		remove_proc_entry(FILENAME_KEEPALIVE, ch->procdir);		remove_proc_entry(FILENAME_DLCI, ch->procdir);	}	kfree(fr);	ch->LINE_privdata = NULL;	MOD_DEC_USE_COUNT;	return 0;}static int fr_master_init(struct net_device *dev){	struct comx_channel *ch = dev->priv;	struct fr_data *fr;	struct proc_dir_entry *new_file;	if ((fr = ch->LINE_privdata = kmalloc(sizeof(struct fr_data), 	    GFP_KERNEL)) == NULL) {		return -ENOMEM;	}	memset(fr, 0, sizeof(struct fr_data));	fr->master = dev;	// this means master	fr->dlci = 0;		// let's say default	dev->flags	= IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;	dev->type	= ARPHRD_FRAD;	dev->mtu	= 1500;	dev->hard_header_len    = 4;			dev->addr_len	= 0;	ch->LINE_rx	= fr_rx;	ch->LINE_tx	= fr_tx;	ch->LINE_status = fr_status;	ch->LINE_open	= fr_open;	ch->LINE_close	= fr_close;	ch->LINE_xmit	= fr_xmit;	ch->LINE_header	= fr_header;	ch->LINE_rebuild_header	= NULL;	ch->LINE_statistics = fr_statistics;	if ((new_file = create_proc_entry(FILENAME_DLCI, S_IFREG | 0644, 	    ch->procdir)) == NULL) {		goto cleanup_LINE_privdata;	}	new_file->data = (void *)new_file;	new_file->read_proc = &fr_read_proc;	new_file->write_proc = &fr_write_proc;	new_file->size = 5;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_KEEPALIVE, S_IFREG | 0644, 	    ch->procdir)) == NULL) {		goto cleanup_filename_dlci;	}	new_file->data = (void *)new_file;	new_file->read_proc = &fr_read_proc;	new_file->write_proc = &fr_write_proc;	new_file->size = 4;	new_file->nlink = 1;	fr_set_keepalive(dev, 0);	MOD_INC_USE_COUNT;	return 0;cleanup_filename_dlci:	 remove_proc_entry(FILENAME_DLCI, ch->procdir);cleanup_LINE_privdata:	kfree(fr);	return -EIO;}static int fr_slave_init(struct net_device *dev){	struct comx_channel *ch = dev->priv;	struct fr_data *fr;	struct proc_dir_entry *new_file;	if ((fr = ch->LINE_privdata = kmalloc(sizeof(struct fr_data), 	    GFP_KERNEL)) == NULL) {		return -ENOMEM;	}	memset(fr, 0, sizeof(struct fr_data));	dev->flags	= IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;	dev->type	= ARPHRD_DLCI;	dev->mtu	= 1500;	dev->hard_header_len    = 4;			dev->addr_len	= 0;	ch->LINE_rx	= fr_rx;	ch->LINE_tx	= fr_tx;	ch->LINE_status = fr_status;	ch->LINE_open	= fr_open;	ch->LINE_close	= fr_close;	ch->LINE_xmit	= fr_xmit;	ch->LINE_header	= fr_header;	ch->LINE_rebuild_header	= NULL;	ch->LINE_statistics = fr_statistics;	if ((new_file = create_proc_entry(FILENAME_DLCI, S_IFREG | 0644, 	    ch->procdir)) == NULL) {		goto cleanup_LINE_privdata;	}		new_file->data = (void *)new_file;	new_file->read_proc = &fr_read_proc;	new_file->write_proc = &fr_write_proc;	new_file->size = 5;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_MASTER, S_IFREG | 0644, 	    ch->procdir)) == NULL) {		goto cleanup_filename_dlci;	}	new_file->data = (void *)new_file;	new_file->read_proc = &fr_read_proc;	new_file->write_proc = &fr_write_proc;	new_file->size = 10;	new_file->nlink = 1;	MOD_INC_USE_COUNT;	return 0;cleanup_filename_dlci:         remove_proc_entry(FILENAME_DLCI, ch->procdir);cleanup_LINE_privdata:	kfree(fr);	return -EIO;}static int dlci_open(struct net_device *dev){	struct comx_channel *ch = dev->priv;	ch->init_status |= HW_OPEN;	MOD_INC_USE_COUNT;	return 0;}static int dlci_close(struct net_device *dev){	struct comx_channel *ch = dev->priv;	ch->init_status &= ~HW_OPEN;	MOD_DEC_USE_COUNT;	return 0;}static int dlci_txe(struct net_device *dev){	struct comx_channel *ch = dev->priv;	struct fr_data *fr = ch->LINE_privdata;	if (!fr->master) {		return 0;	}	ch = fr->master->priv;	fr = ch->LINE_privdata;	return ch->HW_txe(fr->master);}static int dlci_statistics(struct net_device *dev, char *page) {	return 0;}static int dlci_init(struct net_device *dev){	struct comx_channel *ch = dev->priv;	ch->HW_open = dlci_open;	ch->HW_close = dlci_close;	ch->HW_txe = dlci_txe;	ch->HW_statistics = dlci_statistics;	/* Nincs egyeb hw info, mert ugyis a fr->master-bol fog minden kiderulni */	MOD_INC_USE_COUNT;	return 0;}static int dlci_exit(struct net_device *dev){	struct comx_channel *ch = dev->priv;	ch->HW_open = NULL;	ch->HW_close = NULL;	ch->HW_txe = NULL;	ch->HW_statistics = NULL;	MOD_DEC_USE_COUNT;	return 0;}static int dlci_dump(struct net_device *dev){	printk(KERN_INFO "dlci_dump %s, HOGY MI ???\n", dev->name);	return -1;}static struct comx_protocol fr_master_protocol = {	name:		"frad", 	version:	VERSION,	encap_type:	ARPHRD_FRAD, 	line_init:	fr_master_init, 	line_exit:	fr_exit, };static struct comx_protocol fr_slave_protocol = {	name:		"ietf-ip", 	version:	VERSION,	encap_type:	ARPHRD_DLCI, 	line_init:	fr_slave_init, 	line_exit:	fr_exit, };static struct comx_hardware fr_dlci = { 	name:		"dlci", 	version:	VERSION,	hw_init:	dlci_init, 	hw_exit:	dlci_exit, 	hw_dump:	dlci_dump, };#ifdef MODULE#define comx_proto_fr_init init_module#endifint __init comx_proto_fr_init(void){	int ret; 	if ((ret = comx_register_hardware(&fr_dlci))) {		return ret;	}	if ((ret = comx_register_protocol(&fr_master_protocol))) {		return ret;	}	return comx_register_protocol(&fr_slave_protocol);}#ifdef MODULEvoid cleanup_module(void){	comx_unregister_hardware(fr_dlci.name);	comx_unregister_protocol(fr_master_protocol.name);	comx_unregister_protocol(fr_slave_protocol.name);}#endif /* MODULE */

⌨️ 快捷键说明

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