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

📄 netiucv.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
/** * Transmit a packet. * This is a helper function for netiucv_tx(). * * @param conn Connection to be used for sending. * @param skb Pointer to struct sk_buff of packet to send. *            The linklevel header has already been set up *            by netiucv_tx(). * * @return 0 on success, -ERRNO on failure. (Never fails.) */static intnetiucv_transmit_skb(iucv_connection *conn, struct sk_buff *skb) {	unsigned long saveflags;	ll_header header;	int       rc = 0;	if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) {		int l = skb->len + NETIUCV_HDRLEN;		spin_lock_irqsave(&conn->collect_lock, saveflags);		if (conn->collect_len + l >		    (conn->max_buffsize - NETIUCV_HDRLEN))			rc = -EBUSY;		else {			atomic_inc(&skb->users);			skb_queue_tail(&conn->collect_queue, skb);			conn->collect_len += l;		}		spin_unlock_irqrestore(&conn->collect_lock, saveflags);	} else {		struct sk_buff *nskb = skb;		/**		 * Copy the skb to a new allocated skb in lowmem only if the		 * data is located above 2G in memory or tailroom is < 2.		 */		unsigned long hi =			((unsigned long)(skb->tail + NETIUCV_HDRLEN)) >> 31;		int copied = 0;		if (hi || (skb_tailroom(skb) < 2)) {			nskb = alloc_skb(skb->len + NETIUCV_HDRLEN +					 NETIUCV_HDRLEN, GFP_ATOMIC | GFP_DMA);			if (!nskb) {				printk(KERN_WARNING				       "%s: Could not allocate tx_skb\n",				       conn->netdev->name);				rc = -ENOMEM;			} else {				skb_reserve(nskb, NETIUCV_HDRLEN);				memcpy(skb_put(nskb, skb->len),				       skb->data, skb->len);			}			copied = 1;		}		/**		 * skb now is below 2G and has enough room. Add headers.		 */		header.next = nskb->len + NETIUCV_HDRLEN;		memcpy(skb_push(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);		header.next = 0;		memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header,  NETIUCV_HDRLEN);		conn->retry = 0;		fsm_newstate(conn->fsm, CONN_STATE_TX);		fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,			     CONN_EVENT_TIMER, conn);		conn->prof.send_stamp = xtime;				rc = iucv_send(conn->pathid, NULL, 0, 0,			       /* Shut up, gcc! nskb is always below 2G. */			       (__u32)(((unsigned long)nskb)&0xffffffff), 0,			       nskb->data, nskb->len);		conn->prof.doios_single++;		conn->prof.txlen += skb->len;		if (rc != 0) {			fsm_deltimer(&conn->timer);			if (copied)				dev_kfree_skb(nskb);			else {				/**				 * Remove our headers. They get added				 * again on retransmit.				 */				skb_pull(skb, NETIUCV_HDRLEN);				skb_trim(skb, skb->len - NETIUCV_HDRLEN);			}		} else {			if (copied)				dev_kfree_skb(skb);		}	}	return rc;}/** * Interface API for upper network layers *****************************************************************************//** * Open an interface. * Called from generic network layer when ifconfig up is run. * * @param dev Pointer to interface struct. * * @return 0 on success, -ERRNO on failure. (Never fails.) */static intnetiucv_open(net_device *dev) {	MOD_INC_USE_COUNT;	SET_DEVICE_START(dev, 1);	fsm_event(((netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START, dev);	return 0;}/** * Close an interface. * Called from generic network layer when ifconfig down is run. * * @param dev Pointer to interface struct. * * @return 0 on success, -ERRNO on failure. (Never fails.) */static intnetiucv_close(net_device *dev) {	SET_DEVICE_START(dev, 0);	fsm_event(((netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);	MOD_DEC_USE_COUNT;	return 0;}/** * Start transmission of a packet. * Called from generic network device layer. * * @param skb Pointer to buffer containing the packet. * @param dev Pointer to interface struct. * * @return 0 if packet consumed, !0 if packet rejected. *         Note: If we return !0, then the packet is free'd by *               the generic network layer. */static int netiucv_tx(struct sk_buff *skb, net_device *dev){	int          rc = 0;	netiucv_priv *privptr = (netiucv_priv *)dev->priv;	/**	 * Some sanity checks ...	 */	if (skb == NULL) {		printk(KERN_WARNING "%s: NULL sk_buff passed\n", dev->name);		privptr->stats.tx_dropped++;		return 0;	}	if (skb_headroom(skb) < (NETIUCV_HDRLEN)) {		printk(KERN_WARNING		       "%s: Got sk_buff with head room < %ld bytes\n",		       dev->name, NETIUCV_HDRLEN);		dev_kfree_skb(skb);		privptr->stats.tx_dropped++;		return 0;	}	/**	 * If connection is not running, try to restart it	 * notify anybody about a link failure and throw	 * away packet. 	 */	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {		fsm_event(privptr->fsm, DEV_EVENT_START, dev);		dst_link_failure(skb);		dev_kfree_skb(skb);		privptr->stats.tx_dropped++;		privptr->stats.tx_errors++;		privptr->stats.tx_carrier_errors++;		return 0;	}	if (netiucv_test_and_set_busy(dev))		return -EBUSY;	dev->trans_start = jiffies;	if (netiucv_transmit_skb(privptr->conn, skb) != 0)		rc = 1;	netiucv_clear_busy(dev);	return rc;}/** * Returns interface statistics of a device. * * @param dev Pointer to interface struct. * * @return Pointer to stats struct of this interface. */static struct net_device_stats *netiucv_stats (net_device * dev){	return &((netiucv_priv *)dev->priv)->stats;}/** * Sets MTU of an interface. * * @param dev     Pointer to interface struct. * @param new_mtu The new MTU to use for this interface. * * @return 0 on success, -EINVAL if MTU is out of valid range. *         (valid range is 576 .. NETIUCV_MTU_MAX). */static intnetiucv_change_mtu (net_device * dev, int new_mtu){	if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}/** * procfs related structures and routines *****************************************************************************/static net_device *find_netdev_by_ino(unsigned long ino){	iucv_connection *conn = connections;	net_device *dev = NULL;	netiucv_priv *privptr;	while (conn) {		if (conn->netdev != dev) {			dev = conn->netdev;			privptr = (netiucv_priv *)dev->priv;			if ((privptr->proc_buffer_entry->low_ino == ino) ||			    (privptr->proc_user_entry->low_ino == ino)   ||			    (privptr->proc_stat_entry->low_ino == ino)     )				return dev;		}		conn = conn->next;	}	return NULL;}#if LINUX_VERSION_CODE < 0x020363/** * Lock the module, if someone changes into * our proc directory. */static voidnetiucv_fill_inode(struct inode *inode, int fill){	if (fill) {		MOD_INC_USE_COUNT;	} else		MOD_DEC_USE_COUNT;}#endif#define CTRL_BUFSIZE 40static intnetiucv_buffer_open(struct inode *inode, struct file *file){	file->private_data = kmalloc(CTRL_BUFSIZE, GFP_KERNEL);	if (file->private_data == NULL)		return -ENOMEM;	MOD_INC_USE_COUNT;	return 0;}static intnetiucv_buffer_close(struct inode *inode, struct file *file){	kfree(file->private_data);	MOD_DEC_USE_COUNT;	return 0;}static ssize_tnetiucv_buffer_write(struct file *file, const char *buf, size_t count,			   loff_t *off){	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;	net_device   *dev;	netiucv_priv *privptr;	char         *e;	int          bs1;	char         tmp[CTRL_BUFSIZE];	if (!(dev = find_netdev_by_ino(ino)))		return -ENODEV;	if (off != &file->f_pos)		return -ESPIPE;	privptr = (netiucv_priv *)dev->priv;	if (count >= 39)		return -EINVAL;	if (copy_from_user(tmp, buf, count))		return -EFAULT;	tmp[count+1] = '\0';	bs1 = simple_strtoul(tmp, &e, 0);	if ((bs1 > NETIUCV_BUFSIZE_MAX) ||	    (e && (!isspace(*e))))		return -EINVAL;	if ((dev->flags & IFF_RUNNING) &&	    (bs1 < (dev->mtu + NETIUCV_HDRLEN + 2)))		return -EINVAL;	if (bs1 < (576 + NETIUCV_HDRLEN + NETIUCV_HDRLEN))		return -EINVAL;	privptr->conn->max_buffsize = bs1;	if (!(dev->flags & IFF_RUNNING))		dev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN;	privptr->conn->flags |= CONN_FLAGS_BUFSIZE_CHANGED;	return count;}static ssize_tnetiucv_buffer_read(struct file *file, char *buf, size_t count, loff_t *off){	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;	char *sbuf = (char *)file->private_data;	net_device *dev;	netiucv_priv *privptr;	ssize_t ret = 0;	char *p = sbuf;	int l;	if (!(dev = find_netdev_by_ino(ino)))		return -ENODEV;	if (off != &file->f_pos)		return -ESPIPE;	privptr = (netiucv_priv *)dev->priv;	if (file->f_pos == 0)		sprintf(sbuf, "%d\n", privptr->conn->max_buffsize);	l = strlen(sbuf);	p = sbuf;	if (file->f_pos < l) {		p += file->f_pos;		l = strlen(p);		ret = (count > l) ? l : count;		if (copy_to_user(buf, p, ret))			return -EFAULT;	}	file->f_pos += ret;	return ret;}static intnetiucv_user_open(struct inode *inode, struct file *file){	file->private_data = kmalloc(CTRL_BUFSIZE, GFP_KERNEL);	if (file->private_data == NULL)		return -ENOMEM;	MOD_INC_USE_COUNT;	return 0;}static intnetiucv_user_close(struct inode *inode, struct file *file){	kfree(file->private_data);	MOD_DEC_USE_COUNT;	return 0;}static ssize_tnetiucv_user_write(struct file *file, const char *buf, size_t count,			   loff_t *off){	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;	net_device   *dev;	netiucv_priv *privptr;	int          i;	char         *p;	char         tmp[CTRL_BUFSIZE];	char         user[9];	if (!(dev = find_netdev_by_ino(ino)))		return -ENODEV;	if (off != &file->f_pos)		return -ESPIPE;	privptr = (netiucv_priv *)dev->priv;	if (count >= 39)		return -EINVAL;	if (copy_from_user(tmp, buf, count))		return -EFAULT;	tmp[count+1] = '\0';	memset(user, ' ', sizeof(user));	user[8] = '\0';	for (p = tmp, i = 0; *p && (!isspace(*p)); p++) {		if (i > 7)			return -EINVAL;		user[i++] = *p;	}	if (memcmp(user, privptr->conn->userid, 8) != 0) {		/* username changed */		if (dev->flags & IFF_RUNNING)			return -EBUSY;	}	memcpy(privptr->conn->userid, user, 9);	return count;}static ssize_tnetiucv_user_read(struct file *file, char *buf, size_t count, loff_t *off){	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;	char *sbuf = (char *)file->private_data;	net_device *dev;	netiucv_priv *privptr;	ssize_t ret = 0;	char *p = sbuf;	int l;	if (!(dev = find_netdev_by_ino(ino)))		return -ENODEV;	if (off != &file->f_pos)		return -ESPIPE;	privptr = (netiucv_priv *)dev->priv;	if (file->f_pos == 0)		sprintf(sbuf, "%s\n",			netiucv_printname(privptr->conn->userid));	l = strlen(sbuf);	p = sbuf;	if (file->f_pos < l) {		p += file->f_pos;		l = strlen(p);		ret = (count > l) ? l : count;		if (copy_to_user(buf, p, ret))			return -EFAULT;	}	file->f_pos += ret;	return ret;}#define STATS_BUFSIZE 2048static intnetiucv_stat_open(struct inode *inode, struct file *file){	file->private_data = kmalloc(STATS_BUFSIZE, GFP_KERNEL);	if (file->private_data == NULL)		return -ENOMEM;	MOD_INC_USE_COUNT;	return 0;}static intnetiucv_stat_close(struct inode *inode, struct file *file){	kfree(file->private_data);	MOD_DEC_USE_COUNT;	return 0;}static ssize_tnetiucv_stat_write(struct file *file, const char *buf, size_t count, loff_t *off){	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;	net_device *dev;	netiucv_priv *privptr;	if (!(dev = find_netdev_by_ino(ino)))		return -ENODEV;	privptr = (netiucv_priv *)dev->priv;	privptr->conn->prof.maxmulti = 0;	privptr->conn->prof.maxcqueue = 0;	privptr->conn->prof.doios_single = 0;	privptr->conn->prof.doios_multi = 0;	privptr->conn->prof.txlen = 0;	privptr->conn->prof.tx_time = 0;	return count;}static ssize_tnetiucv_stat_read(struct file *file, char *buf, size_t count, loff_t *off){	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;	char *sbuf = (char *)file->private_data;	net_device *dev;	netiucv_priv *privptr;	ssize_t ret = 0;	char *p = sbuf;	int l;	if (!(dev = find_netdev_by_ino(ino)))		return -ENODEV;	if (off != &file->f_pos)		return -ESPIPE;	privptr = (netiucv_priv *)dev->priv;	if (file->f_pos == 0) {		p += sprintf(p, "Device FSM state: %s\n",			     fsm_getstate_str(privptr->fsm));		p += sprintf(p, "Connection FSM state: %s\n",			     fsm_getstate_str(privptr->conn->fsm));		p += sprintf(p, "Max. TX buffer used: %ld\n",			     privptr->conn->prof.maxmulti);		p += sprintf(p, "Max. chained SKBs: %ld\n",			     privptr->conn->prof.maxcqueue);		p += sprintf(p, "TX single write ops: %ld\n",			     privptr->conn->prof.doios_single);		p += sprintf(p, "TX multi write ops: %ld\n",			     privptr->conn->prof.doios_multi);		p += sprintf(p, "Netto bytes written: %ld\n",			     privptr->conn->prof.txlen);		p += sprintf(p, "Max. TX IO-time: %ld\n",			     privptr->conn->prof.tx_time);	}

⌨️ 快捷键说明

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