📄 vnet.c
字号:
static Bool vnet_hub_grabnuts(struct vnet_nut *nut){ Bool retval = TRUE; spin_lock_bh(&vnet_nutLock); if (!nut || !nut->peer || !nut->connected || !nut->peer->connected) { retval = FALSE; goto done; }/* * This check is probably redundant because we set * connected in VNetConnect which if set means * we can grab and refCount will be larger that zero. */ if (nut->refCount == 0 || nut->peer->refCount == 0) { retval = FALSE; goto done; } nut->refCount++; nut->peer->refCount++; done: spin_unlock_bh(&vnet_nutLock); return retval;}static int vnet_hub_getattachednuts(struct vnet_nut *nut){ if (!nut) { // assert failed return 0; } if (!nut->peer) { return 0; } return nut->peer->numbolts;}static int vnet_hub_isbridged(struct vnet_nut *nut){ DBG(KERN_INFO "vnet: vnet_hub_isbridged do in future\n"); return -EFAULT;}static int vnet_isbridged(struct vnet_nut *nut){ if (nut && nut->peer && nut->peer->isBridged) { return nut->peer->isBridged(nut->peer); } return 0;}static void vnet_hub_boltschanged(struct vnet_nut *nut){ DBG(KERN_INFO "vnet: vnet_hub_boltschanged do in future\n");}//chy: ??? maybe usefulstatic void vnet_boltschanged(struct vnet_nut *nut){ if (nut && nut->boltsChanged) { nut->boltsChanged(nut); }}static void vnet_nut_free(struct vnet_nut *nut){ if (nut && nut->free) { nut->free(nut); }}static void vnet_hub_free_nut(struct vnet_nut *nut){ struct vnet_hub *hub = (struct vnet_hub*)nut->private; DBG(KERN_INFO "vnet: vnet_hub_free_nut begin\n"); if (nut != &hub->nut[nut->index]) { printk(KERN_DEBUG "vnet: bad free of hub nut\n"); return; } //chy: do it in future /* if (this->procEntry) { VNetProc_RemoveEntry(this->procEntry, NULL); this->procEntry = NULL; } */ nut->private = NULL;}static Bool vnet_hub_cycledetect(struct vnet_nut *nut, int generation){ DBG(KERN_INFO "vnet: vnet_hub_cycledetect do in future\n"); return FALSE; }//chy: ??? maybe useful/*static Bool vnet_cycledetect(struct vnet_nut *nut, int generation) { if (nut && nut->cycleDetect) { return nut->cycleDetect(nut, generation); } return FALSE;}*/struct vnet_nut* vnet_hub_disconnect(struct vnet_nut *nut){ struct vnet_nut *peer = NULL; printk(KERN_INFO "vnet: vnet_hub_disconnect begin\n"); spin_lock_bh(&vnet_nutLock); peer = nut->peer; /* * Tell others that we are disconnected to make sure no one grabs * the nuts and make us wait for ever. */ nut->connected = FALSE; peer->connected = FALSE; nut->refCount--; peer->refCount--; /* * We need to wait for potential users of these nuts to release them * before we can disconnect the nuts. */ while (nut->refCount > 0) { printk(KERN_INFO "vnet: ??? vnet_hub_disconnect nut->refCount >1!!!!\n"); spin_unlock_bh(&vnet_nutLock); wait_event(nut->waitQueue, (nut->refCount == 0)); spin_lock_bh(&vnet_nutLock); } /* just to make sure that the peer is correctly freed as well */ if (peer->refCount != 0) { /* Both nuts should always have the same refcount. */ printk(KERN_INFO "vnet:??? vnet_hub_disconnect nut->perr->refCount >1!!!!\n"); peer = NULL; goto done; } nut->peer = NULL; peer->peer = NULL; done: spin_unlock_bh(&vnet_nutLock); //chy: do in future /* if (peer) { if (peer->numPorts) { VNetPortsChanged(nut); } if (nut->numPorts) { VNetPortsChanged(peer); } } */ printk(KERN_INFO "vnet: vnet_hub_disconnect end\n"); return peer;}int vnet_hub_connect(struct vnet_bolt *bolt, struct vnet_nut *nut){ static int vnetGeneration = 0; //Bool foundCycle; int retval = 0; struct vnet_nut *nut1, *nut2; DBG(KERN_INFO "vnet: vnet_hub_connect begin, bolt is %x, nut is%x\n",(unsigned int)bolt,(unsigned int)nut); nut1=&(bolt->nut); nut2=nut; spin_lock_bh(&vnet_nutLock); vnetGeneration++; if (nut1->refCount != 0 || nut2->refCount != 0) { retval = -EDEADLK; goto done; } //chy:not very clear ???, leave to future /* foundCycle = vnet_hub_cycledetect(nut1, vnetGeneration); if (foundCycle) { retval = -EDEADLK; goto done; } foundCycle = vnet_hub_cycledetect(nut2, vnetGeneration); if (foundCycle) { retval = -EDEADLK; goto done; } */ /* Connect the nuts */ nut1->peer = nut2; nut2->peer = nut1; /* Make the nuts grabbable */ nut1->connected = TRUE; nut2->connected = TRUE; nut1->refCount++; nut2->refCount++; done: spin_unlock_bh(&vnet_nutLock); //chy:not very clear ???, leave to future /* if (retval == 0) { if (nut2->numbolts) { vnet_hub_boltschanged(nut1); } if (nut1->numbolts) { vnet_hub_boltschanged(nut2); } } */ DBG(KERN_INFO "vnet: vnet_hub_connect end retval %d\n",retval); return retval;}void vnet_hub_recv(struct vnet_nut *srcnut, struct sk_buff *skb) { struct vnet_hub *hub=(struct vnet_hub *)srcnut->private; struct sk_buff *clone; struct vnet_nut * nut; int i; DBG(KERN_INFO "vnet: vnet_hub_recv begin\n"); hub->stats[srcnut->index]++; //chy: simualte a switch in the future for (i=0; i<NUM_NUTS_PER_HUB; i++) { nut = &hub->nut[i]; if ( nut->private /* allocated */ && nut->peer /* and connected */ && (nut != srcnut)) { /* and not a loop */ clone = skb_clone(skb, GFP_ATOMIC); if (clone) { if (nut->peer->rcv) { nut->peer->rcv(nut->peer, clone); }else{ printk("vnet: vnet_hub_recv peer->rcv is NULL!!!"); dev_kfree_skb(clone); } } else{ printk(KERN_INFO "vnet: vnet_hub_recv skb_clone failed!!!\n"); } } } dev_kfree_skb(skb); DBG(KERN_INFO "vnet: vnet_hub_recv end\n");}struct vnet_nut * vnet_hub_alloc_nut(int hubnum){ struct vnet_hub *hub = vnetHub[hubnum]; struct vnet_nut *nut; int i; DBG(KERN_INFO "vnet: vnet_hub_alloc_nut hubnum %d begin\n", hubnum); if (!hub) { DBG(KERN_INFO "vnet: vnet_hub_alloc_nut hub %d does not exist, allocating memory.\n", hubnum); hub = (struct vnet_hub *)kmalloc(sizeof(struct vnet_hub), GFP_KERNEL); if(!hub) { printk(KERN_INFO "vnet: vnet_hub_alloc_nut can not malloc hub struct\n"); return NULL; } DBG(KERN_INFO "vnet: vnet_hub_alloc_nut init nuts in hub\n"); for (i=0; i<NUM_NUTS_PER_HUB; i++) { nut = &hub->nut[i]; /* * The private field indicates if this nut is allocated. * Null means free, otherwise the nut is allocated and it * should point back to the hub. */ nut->type=VNET_HUB_NUT; nut->peer = NULL; nut->numbolts = 0; sprintf(nut->name, "hub%d.%d", hubnum, i); nut->refCount = 0; nut->connected = FALSE; nut->private = NULL; nut->index = i; //chy: will do it in the future //nut->procEntry = NULL; init_waitqueue_head(&nut->waitQueue); nut->free = vnet_hub_free_nut; nut->rcv = vnet_hub_recv; nut->cycleDetect = vnet_hub_cycledetect; nut->boltsChanged = vnet_hub_boltschanged; nut->isBridged = vnet_hub_isbridged; hub->stats[i]=0; } hub->num = hubnum; hub->totalbolts = 0; hub->mygeneration = 0; vnetHub[hubnum] = hub; } DBG(KERN_INFO "vnet: vnet_hub_alloc begin find a free nut\n"); for (i=0; i<NUM_NUTS_PER_HUB; i++) { nut = &hub->nut[i]; DBG(KERN_INFO "vnet: vnet_hub_alloc i %d \n",i); if (!nut->private) { //ASSERT(nut->refCount == 0); /* * Make proc entry for this nut. */ /* chy: do it in the future retval = VNetProc_MakeEntry(NULL, nut->name, S_IFREG, &nut->procEntry); if (retval) { if (retval == -ENXIO) { nut->procEntry = NULL; } else { return NULL; } } else { nut->procEntry = NULL; } */ /* * OK, now allocate this nut. */ nut->numbolts = hub->totalbolts; nut->private = hub; nut->peer = NULL; DBG(KERN_INFO "vnet: vnet_hub_alloc find a free nut and allocate it\n"); return nut; } } printk(KERN_INFO "vnet vnet_hub_alloc can not find a free nut\n"); return NULL;}void vnet_hub_init(void){ DBG(KERN_INFO "vnet: vnet_hub_init begin\n"); int i; for (i=0; i<VNET_NUM_HUBS; i++) { vnetHub[i] = NULL; } DBG(KERN_INFO "vnet: vnet_hub_init end.\n");}void vnet_hub_free(void){ int i,j; j=0; DBG(KERN_INFO "vnet: vnet_hub_free begin\n"); for (i=0; i<VNET_NUM_HUBS; i++) { if(vnetHub[i]) { kfree(vnetHub[i]); DBG(KERN_INFO "vnet: vnet_hub_free kfree %d hub.\n", i); j++; } } DBG(KERN_INFO "vnet: vnet_hub_free end, total free num %d.\n", j);}static struct file_operations vnet_fops = { owner: THIS_MODULE, read: vnet_chr_read, write: vnet_chr_write, poll: vnet_chr_poll, ioctl: vnet_chr_ioctl, open: vnet_chr_open, release:vnet_chr_close, fasync: vnet_chr_fasync };/* chy: the misc dev 's major num is 10 */static struct miscdevice vnet_miscdev={ VNET_MINOR, "net/vnet", &vnet_fops};int __init vnet_init(void){ printk(KERN_INFO "Universal VNET device driver %s " "(C)2003 SkyEye Developer: Chen Yu\n", VNET_VER); vnet_hub_init(); spin_lock_init(&vnet_nutLock); spin_lock_init(&vnet_boltLock); if(vnet_procfs_init()){ printk(KERN_ERR "vnet: could not register proc fs\n"); return -ENOENT; } DBG(KERN_INFO "vnet: register proc fs over!\n"); if (misc_register(&vnet_miscdev)) { printk(KERN_ERR "vnet: Can't register misc device %d\n", VNET_MINOR); return -EIO; } DBG(KERN_INFO "vnet: register miscdev over!\n"); DBG(KERN_INFO "vnet: vnet_init successfully!\n"); return 0;}void vnet_cleanup(void){ vnet_hub_free(); vnet_procfs_cleanup(); DBG(KERN_INFO "vnet: proc fs cleanup over!\n"); misc_deregister(&vnet_miscdev); DBG(KERN_INFO "vnet: miscdev deregister over!\n"); DBG(KERN_INFO "vnet: vnet_cleanup successfully!\n");}module_init(vnet_init);module_exit(vnet_cleanup);#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -