Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


vnet cleanup
[palacios.git] / palacios / src / devices / vnet_nic.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Lei Xia <lxia@northwestern.edu>
15  *               
16  *
17  * This is free software.  You are permitted to use,
18  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19  */
20 //backend device for Virtio NIC
21
22 #include <palacios/vmm_vnet.h>
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_dev_mgr.h>
25 #include <devices/lnx_virtio_pci.h>
26 #include <palacios/vm_guest_mem.h>
27 #include <devices/pci.h>
28
29
30 #ifndef CONFIG_DEBUG_VNET_NIC
31 #undef PrintDebug
32 #define PrintDebug(fmt, args...)
33 #endif
34
35
36 struct vnet_nic_state {
37     char mac[6];
38     struct guest_info * core;
39         
40     void *frontend_data;
41     int (*frontend_input)(struct v3_vm_info *info, 
42                           uchar_t * buf,
43                           uint32_t size,
44                           void *private_data);
45 };
46
47 //used when virtio_nic get a packet from guest and send it to the backend
48 static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){
49     PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data);
50     struct v3_vnet_pkt * pkt = NULL; 
51
52     // fill in packet
53
54     v3_vnet_send_pkt(pkt);
55     return 0;
56 }
57
58
59 // We need to make this dynamically allocated
60 static struct v3_dev_net_ops net_ops = {
61     .send = vnet_send, 
62 };
63
64 static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void * private_data){
65     //  struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
66         
67     // PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic);  
68
69     return net_ops.recv(pkt->data, pkt->size, net_ops.frontend_data);
70 }
71
72 #if 0
73 static int sendto_buf(struct vnet_nic_dev_state *vnetnic_dev, uchar_t * buf, uint_t size) {
74     struct eth_pkt *pkt;
75
76     pkt = (struct eth_pkt *)V3_Malloc(sizeof(struct eth_pkt));
77     if(pkt == NULL){
78         PrintError("Vnet NIC: Memory allocate fails\n");
79         return -1;
80     }
81   
82     pkt->size = size;
83     memcpy(pkt->data, buf, size);
84     v3_enqueue(vnetnic_dev->inpkt_q, (addr_t)pkt);
85         
86     PrintDebug("Vnet NIC: sendto_buf: packet: (size:%d)\n", (int)pkt->size);
87
88     return pkt->size;
89 }
90
91 /*
92   *called in svm/vmx handler
93   *iteative handled the unsent packet in incoming packet queues for
94   *all virtio nic devices in this guest
95   */
96 int v3_virtionic_pktprocess(struct guest_info * info)
97 {
98     struct eth_pkt *pkt = NULL;
99     struct virtio_net_state *net_state;
100     int i;
101
102     //PrintDebug("Virtio NIC: processing guest %p\n", info);
103     for (i = 0; i < net_idx; i++) {
104         while (1) {
105             net_state = temp_net_states[i];
106             if(net_state->dev->vm != info)
107                 break;
108
109             pkt = (struct eth_pkt *)v3_dequeue(net_state->inpkt_q);
110             if(pkt == NULL) 
111                 break;
112                         
113             if (send_pkt_to_guest(net_state, pkt->data, pkt->size, 1, NULL)) {
114                 PrintDebug("Virtio NIC: %p In pkt_handle: send one packet! pt length %d\n", 
115                                 net_state, (int)pkt->size);  
116             } else {
117                 PrintDebug("Virtio NIC: %p In pkt_handle: Fail to send one packet, pt length %d, discard it!\n", 
118                                 net_state, (int)pkt->size); 
119             }
120         
121             V3_Free(pkt);
122         }
123     }
124     
125     return 0;
126 }
127
128
129 /*
130   *called in svm/vmx handler
131   *iteative handled the unsent packet in incoming packet queues for
132   *all virtio nic devices in this guest
133   */
134 int v3_vnetnic_pktprocess(struct guest_info * info)
135 {
136  
137     return 0;
138 }
139
140 #endif
141
142 //register a virtio device to the vnet as backend
143 int register_to_vnet(struct v3_vm_info * vm,
144                      struct vnet_nic_state *vnet_nic,
145                      char *dev_name,
146                      uchar_t mac[6]) { 
147    
148     PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic);
149         
150     v3_vnet_add_dev(vm, dev_name, mac, virtio_input, (void *)vnet_nic);
151
152
153
154     return 0;
155 }
156
157 static int vnet_nic_free(struct vm_device * dev) {
158     return 0;
159 }
160
161 static struct v3_device_ops dev_ops = {
162     .free = vnet_nic_free,
163     .reset = NULL,
164     .start = NULL,
165     .stop = NULL,
166 };
167
168 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
169     struct vnet_nic_state * vnetnic = NULL;
170     char * name = v3_cfg_val(cfg, "name");
171
172     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
173
174     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
175     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
176
177     struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic);
178
179     if (v3_attach_device(vm, dev) == -1) {
180         PrintError("Could not attach device %s\n", name);
181         return -1;
182     }
183
184     if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), 
185                            &net_ops, frontend_cfg, vnetnic) == -1) {
186         PrintError("Could not connect %s to frontend %s\n", 
187                    name, v3_cfg_val(frontend_cfg, "tag"));
188         return -1;
189     }
190
191     if (register_to_vnet(vm, vnetnic, name, vnetnic->mac) == -1) {
192         return -1;
193     }
194
195     PrintDebug("Vnet-nic device %s initialized\n", name);
196
197     return 0;
198 }
199
200 device_register("VNET_NIC", vnet_nic_init)