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

📄 vnet.c

📁 嵌入式系统的网络仿真
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  VNET - Virtual Net Switch device driver. *  Copyright (C) 2003  *       Skyeye Develop Group <skyeye-developer@lists.sf.linuxforum.net> *	 Chen Yu <chenyu@hpclab.cs.tsinghua.edu.cn> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *  GNU General Public License for more details. * *  $Id: vnet.c,v 1.7 2003/06/06 13:28:49 chenyu Exp $ *//* * 06/05/2003 vnet 0.2.0  *            Chen Yu <chenyu@hpclab.cs.tsinghua.edu.cn> */#define VNET_VER "0.2.0"#include <linux/config.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/poll.h>#include <linux/fcntl.h>#include <linux/init.h>#include <linux/random.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/miscdevice.h>#include <linux/rtnetlink.h>#include <linux/if.h>#include <linux/if_arp.h>#include <linux/if_ether.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/io.h>#include <linux/proc_fs.h>#include <linux/file.h>//#include <linux/if_tun.h>#include "if_vnet.h"#ifdef VNET_DEBUG//static int debug;#endif//global datastatic struct vnet_hub *vnetHub[VNET_NUM_HUBS];spinlock_t vnet_nutLock;spinlock_t vnet_boltLock ;static struct proc_dir_entry *vnet_procfs_base = NULL;struct vnet_bolt * vnet_bolthead;// function declare/********************vnet_chr_...*************/static int vnet_chr_close(struct inode *inode, struct file *file);static int vnet_chr_fasync(int fd, struct file *file, int on);static int vnet_chr_ioctl(struct inode *inode, struct file *file, 			 unsigned int cmd, unsigned long arg);static int vnet_chr_open(struct inode *inode, struct file * file);static unsigned int vnet_chr_poll(struct file *file, poll_table * wait);static ssize_t vnet_chr_read(struct file * file, char * buf, size_t count, loff_t *pos);//static ssize_t vnet_chr_readv(struct file *file, const struct iovec *iv,//			    unsigned long count, loff_t *pos);static ssize_t vnet_chr_write(struct file * file, const char * buf, 			     size_t count, loff_t *pos);//static ssize_t vnet_chr_writev(struct file * file, const struct iovec *iv, //			      unsigned long count, loff_t *pos);/********************vnet_hostif_...*************/static int vnet_hostif_open(struct net_device *dev);;int vnet_hostif_init(struct net_device *dev);static int vnet_hostif_close(struct net_device *dev);static void vnet_hostif_mclist(struct net_device *dev);static struct net_device_stats *vnet_hostif_stats(struct net_device *dev);static int vnet_hostif_xmit(struct sk_buff *skb, struct net_device *dev);static void vnet_hostif_recv(struct vnet_nut *nut, struct sk_buff *skb);static int vnet_hostif_create(struct inode *inode, struct file *file, struct ifreq *ifr);void vnet_hostif_free(struct vnet_nut *this);int vnet_hostif_procread(char *page,char **start,off_t off,int count,int *eof,void *data);  /********************vnet_guestif_...*************/int vnet_guestif_create(struct vnet_bolt **ret);void vnet_guestif_free(struct vnet_guestif *gif);//int vnet_guestif_ioctl(struct vnet_guestif *gif,int vnet_guestif_ioctl(struct vnet_bolt *bolt,                struct file    *filp,                unsigned int    iocmd,                unsigned long   ioarg);//int vnet_guestif_poll(struct vnet_guestif *gif,int vnet_guestif_poll(struct vnet_bolt *bolt,               struct file  *filp,	       poll_table   *wait);//int vnet_guestif_read(struct vnet_guestif *gif,struct file  *filp, char *buf, size_t count);int vnet_guestif_read(struct vnet_bolt *bolt,struct file  *filp, char *buf, size_t count);void vnet_guestif_recv(struct vnet_nut *this,struct sk_buff  *skb);//int vnet_guestif_write(struct vnet_guestif *gif,struct file  *filp, const char *buf, size_t count);int vnet_guestif_write(struct vnet_bolt *bolt,struct file  *filp, const char *buf, size_t count);void vnet_gusetif_free(struct vnet_nut *this);int vnet_guestif_procread(char *page,char **start,off_t off,int count,int *eof,void *data);  /********************vnet_nut_...*************/static void vnet_nut_release(struct vnet_nut *nut);/********************vnet_bolt_...*************/static void vnet_bolt_addtolist(struct vnet_bolt *bolt);static  void vnet_bolt_removefromlist(struct vnet_bolt *bolt);static int vnet_bolt_print(struct vnet_bolt *bolt, char * buf);/********************vnet_hub_...*************/struct vnet_nut * vnet_hub_alloc_nut(int hubnum);static  void vnet_hub_boltschanged(struct vnet_nut *nut);int vnet_hub_connect(struct vnet_bolt *bolt, struct vnet_nut *nut);struct vnet_nut* vnet_hub_disconnect(struct vnet_nut *nut);static Bool vnet_hub_cycledetect(struct vnet_nut *nut,                int       generation);static int vnet_hub_getattachednuts(struct vnet_nut  *nut);static Bool vnet_hub_grabnuts(struct vnet_nut  *nut);void vnet_hub_init(void);static int vnet_hub_isbridged(struct vnet_nut  *nut);static  void vnet_hub_free_nut(struct vnet_nut *nut);void vnet_hub_recv(struct vnet_nut *nut, struct sk_buff *skb); //--------------------------------------------------------/* *---------------------------------------------------------------------- * * VNetMulticastFilter -- * *      Utility function that filters multicast packets according *      to a 64-bit logical address filter (like the one on the *      lance chipset).  AllMultiFilter lets all packets through. * *      We generate a hash value from the destination MAC address *      and see if it's in our filter.  Broadcast packets have *      already OK'd by PacketMatch, so we don't have to worry *      about that. * *      (This is in the green AMD "Ethernet Controllers" book,  *      page 1-53.) * * Results: *      TRUE if packet is in filter, FALSE if not. * * Side effects: *      None. * *---------------------------------------------------------------------- */#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian *///chy: should change in future !!!!Bool vnet_multicastfilter(uint8 *destAddr,		    uint8 *ladrf){   uint16 hashcode;   int32 crc, poly = CRC_POLYNOMIAL_BE;   int j, bit, byte;      crc = 0xffffffff;                  /* init CRC for each address */   for (byte=0; byte<6; byte++) {     /* for each address byte */      /* process each address bit */       for (bit = *destAddr++,j=0;j<8;j++, bit>>=1) {	 crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0);      }   }   hashcode = (crc & 1);              /* hashcode is 6 LSb of CRC ... */   for (j=0; j<5; j++) {                /* ... in reverse order. */      hashcode = (hashcode << 1) | ((crc>>=1) & 1);   }                                            byte = hashcode >> 3;              /* bit[3-5] -> byte in filter */   bit = 1 << (hashcode & 0x07);      /* bit[0-2] -> bit in byte */   if (ladrf[byte] & bit) {      return TRUE;   } else {      return FALSE;   }}Bool vnet_packetmatch(uint8   *destAddr,                uint8   *ifAddr,				uint8   *ladrf,                uint32   flags){   static uint8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};   return ((flags & IFF_PROMISC)           || VNET_MAC_EQ(destAddr, ifAddr)           || ((flags & IFF_BROADCAST) && VNET_MAC_EQ(destAddr, broadcast))           || ((destAddr[0] & 0x1) && 	       (flags & IFF_ALLMULTI || // allow all multi		     (flags & IFF_MULTICAST && 		      vnet_multicastfilter(destAddr, ladrf)))));}int vnet_procfs_makeentry(struct proc_dir_entry *parent,                  			 char            *name,                  			 int              mode,                  			 struct proc_dir_entry  **ret){   struct proc_dir_entry *ent;   //int retval;   if (!parent) {      parent = vnet_procfs_base;   }   ent = create_proc_entry(name, mode, parent);   *ret = ent;   if (!ent)      return -ENOMEM;   return 0;}/* *---------------------------------------------------------------------- * * VNetProc_RemoveEntry -- * *      Remove a previously installed proc entry. * * Results:  *      None. * * Side effects: *      None. * *---------------------------------------------------------------------- */void vnet_procfs_removeentry(struct proc_dir_entry *node,                     struct proc_dir_entry *parent){   if (!parent) {      parent = vnet_procfs_base;   }      if (node) {      remove_proc_entry(node->name, parent);   }}void vnet_procfs_cleanup(void){   vnet_procfs_removeentry(vnet_procfs_base, &proc_root);   vnet_procfs_base = NULL;}int vnet_procfs_init(void){  	int retval;   	retval = vnet_procfs_makeentry(&proc_root, "vnet", S_IFDIR, &vnet_procfs_base);   	return retval; }/* Network device part of the driver *//* Net device open. */static int vnet_hostif_open(struct net_device *dev){	netif_start_queue(dev);	return 0;}/* Net device close. */static int vnet_hostif_close(struct net_device *dev){	netif_stop_queue(dev);	return 0;}static void vnet_hostif_recv(struct vnet_nut *nut, struct sk_buff *skb){  struct vnet_hostif *hif=(struct vnet_hostif *)nut->private;	  skb->dev=&hif->dev;  skb->protocol=eth_type_trans(skb, &hif->dev);  netif_rx_ni(skb);  hif->stats.rx_packets++;  return;}/* Net device start xmit */static int vnet_hostif_xmit(struct sk_buff *skb, struct net_device *dev){	struct vnet_hostif *hif = (struct vnet_hostif *)dev->priv;	struct vnet_nut *peer;	DBG(KERN_INFO "vnet: vnet_hostif_xmit begin\n");	/* Drop packet if interface is not attached */	if (!hif->attached)		goto drop;	/* Queue packet */	/*	if (skb_queue_len(&vnet->readq) >= dev->tx_queue_len)		goto drop;	*/	peer=hif->bolt.nut.peer;   	if(!peer||!peer->rcv){   		printk("vnet: vnet_hostif_xmit gif->bolt.nut.peer or peer->rcv is NULL!!!\n");   		return -EFAULT;   	}	   	peer->rcv(peer, skb);	hif->stats.tx_packets++;	DBG(KERN_INFO "vnet: vnet_hostif_xmit end\n");	return 0;drop:	hif->stats.tx_dropped++;	kfree_skb(skb);	return 0;}static void vnet_hostif_mclist(struct net_device *dev){	/* Nothing to do for multicast filters. 	 * We always accept all frames. */	printk(KERN_INFO "vnet: vnet_hostif_mclist isn't realized yet!!!!\n");	return;}int vnet_hostif_procread(char    *page,   // IN/OUT: buffer to write into                   char   **start,  // OUT: 0 if file < 4k, else offset into page                   off_t    off,    // IN: offset of read into the file                   int      count,  // IN: maximum number of bytes to read                   int     *eof,    // OUT: TRUE if there is nothing more to read                   void    *data)   // IN: client data - not used{   struct vnet_hostif *hif = (struct vnet_hostif *)data;    int len = 0;   if(!hif){   	 printk("vnet: vnet_hostif_procread hif is NULL!!!\n");   	 return 0;   }      len += vnet_bolt_print(&hif->bolt, page+len);   len += sprintf(page+len, "\n");      *start = 0;   *eof   = 1;   return len;}static struct net_device_stats *vnet_hostif_stats(struct net_device *dev){	struct vnet_hostif *hif = (struct vnet_hostif *)dev->priv;	return &hif->stats;}/* Initialize net device. */int vnet_hostif_init(struct net_device *dev){	struct vnet_hostif *hif = (struct vnet_hostif *)dev->priv;   	DBG(KERN_INFO "vnet: %s: vnet_hostif_init begin\n", hif->dev.name);	SET_MODULE_OWNER(dev);	dev->open = vnet_hostif_open;	dev->hard_start_xmit = vnet_hostif_xmit;	dev->stop = vnet_hostif_close;	dev->get_stats = vnet_hostif_stats;	switch (hif->flags & VNET_TYPE_MASK) {	case VNET_VNET_DEV:		/* Ethernet TAP Device */		dev->set_multicast_list = vnet_hostif_mclist;		/* Generate random Ethernet address.  */		*(u16 *)dev->dev_addr = htons(0x00FF);		get_random_bytes(dev->dev_addr + sizeof(u16), 4);		ether_setup(dev);		memcpy(hif->bolt.paddr,dev->dev_addr,ETH_ALEN);			break;	default: 		printk(KERN_INFO "vnet: vnet_hostif_init unknonw flags\n");		return -EINVAL; 	};	return 0;}/* Character device part *//* Poll */static unsigned int vnet_chr_poll(struct file *file, poll_table * wait){  	struct vnet_guestif *gif = (struct vnet_guestif *)file->private_data;	struct vnet_bolt *bolt;	unsigned int mask;	        //DBG(KERN_INFO "vnet_chr_poll begin\n");	if (!gif)		return -EBADFD;	bolt=&(gif->bolt);        mask=vnet_guestif_poll(bolt, file, wait); 	//DBG(KERN_INFO "vnet_chr_poll end\n");	return mask;}/* Get packet from user space buffer(already verified) */static __inline__ ssize_t vnet_get_user(struct vnet_struct *vnet, struct iovec *iv, size_t count){	struct vnet_pi pi = { 0, __constant_htons(ETH_P_IP) };	struct sk_buff *skb;	size_t len = count;	if (!(vnet->flags & VNET_NO_PI)) {		if ((len -= sizeof(pi)) < 0)			return -EINVAL;		memcpy_fromiovec((void *)&pi, iv, sizeof(pi));	} 	if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {		vnet->stats.rx_dropped++;		return -ENOMEM;	}	skb_reserve(skb, 2);	memcpy_fromiovec(skb_put(skb, len), iv, len);	skb->dev = &vnet->dev;	switch (vnet->flags & VNET_TYPE_MASK) {	case VNET_VNET_DEV:		skb->mac.raw = skb->data;		skb->protocol = pi.proto;		break;	case VNET_TAP_DEV:		skb->protocol = eth_type_trans(skb, &vnet->dev);		break;	};	if (vnet->flags & VNET_NOCHECKSUM)		skb->ip_summed = CHECKSUM_UNNECESSARY; 	netif_rx_ni(skb);   	vnet->stats.rx_packets++;	vnet->stats.rx_bytes += len;	return count;} /* Write */static ssize_t vnet_chr_write(struct file * file, const char * buf, 			     size_t count, loff_t *pos){	struct vnet_guestif *gif = (struct vnet_guestif *)file->private_data;

⌨️ 快捷键说明

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