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.


ffe99dfcbadbe9dfd7ef569f5a6ae98596f75d6d
[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     struct v3_dev_net_ops net_ops;
40 };
41
42 //used when virtio_nic get a packet from guest and send it to the backend
43 static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){
44     PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data);
45     struct v3_vnet_pkt * pkt = NULL; 
46
47     // fill in packet
48     pkt = (struct v3_vnet_pkt *)V3_Malloc(sizeof(struct v3_vnet_pkt));
49
50     if(pkt == NULL){
51         PrintError("Malloc() fails");
52         return -1;
53     }
54
55     pkt->size = len;
56     memcpy(pkt->data, buf, pkt->size);
57
58     //TODO: 
59
60     v3_vnet_send_pkt(pkt);
61     return 0;
62 }
63
64
65 // We need to make this dynamically allocated
66 //static struct v3_dev_net_ops net_ops = {
67 //    .send = vnet_send, 
68 //};
69
70 static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void * private_data){
71     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
72         
73     PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic);     
74
75     return vnetnic->net_ops.recv(pkt->data, pkt->size, vnetnic->net_ops.frontend_data);
76 }
77
78 #if 0
79 static int sendto_buf(struct vnet_nic_dev_state *vnetnic_dev, uchar_t * buf, uint_t size) {
80     struct eth_pkt *pkt;
81
82     pkt = (struct eth_pkt *)V3_Malloc(sizeof(struct eth_pkt));
83     if(pkt == NULL){
84         PrintError("Vnet NIC: Memory allocate fails\n");
85         return -1;
86     }
87   
88     pkt->size = size;
89     memcpy(pkt->data, buf, size);
90     v3_enqueue(vnetnic_dev->inpkt_q, (addr_t)pkt);
91         
92     PrintDebug("Vnet NIC: sendto_buf: packet: (size:%d)\n", (int)pkt->size);
93
94     return pkt->size;
95 }
96
97 /*
98   *called in svm/vmx handler
99   *iteative handled the unsent packet in incoming packet queues for
100   *all virtio nic devices in this guest
101   */
102 int v3_virtionic_pktprocess(struct guest_info * info)
103 {
104     struct eth_pkt *pkt = NULL;
105     struct virtio_net_state *net_state;
106     int i;
107
108     //PrintDebug("Virtio NIC: processing guest %p\n", info);
109     for (i = 0; i < net_idx; i++) {
110         while (1) {
111             net_state = temp_net_states[i];
112             if(net_state->dev->vm != info)
113                 break;
114
115             pkt = (struct eth_pkt *)v3_dequeue(net_state->inpkt_q);
116             if(pkt == NULL) 
117                 break;
118                         
119             if (send_pkt_to_guest(net_state, pkt->data, pkt->size, 1, NULL)) {
120                 PrintDebug("Virtio NIC: %p In pkt_handle: send one packet! pt length %d\n", 
121                                 net_state, (int)pkt->size);  
122             } else {
123                 PrintDebug("Virtio NIC: %p In pkt_handle: Fail to send one packet, pt length %d, discard it!\n", 
124                                 net_state, (int)pkt->size); 
125             }
126         
127             V3_Free(pkt);
128         }
129     }
130     
131     return 0;
132 }
133
134
135 /*
136   *called in svm/vmx handler
137   *iteative handled the unsent packet in incoming packet queues for
138   *all virtio nic devices in this guest
139   */
140 int v3_vnetnic_pktprocess(struct guest_info * info)
141 {
142  
143     return 0;
144 }
145
146 #endif
147
148 //register a virtio device to the vnet as backend
149 int register_to_vnet(struct v3_vm_info * vm,
150                      struct vnet_nic_state *vnet_nic,
151                      char *dev_name,
152                      uchar_t mac[6]) { 
153    
154     PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic);
155         
156     v3_vnet_add_dev(vm, mac, virtio_input, (void *)vnet_nic);
157
158     return 0;
159 }
160
161 static int vnet_nic_free(struct vm_device * dev) {
162     return 0;
163 }
164
165 static struct v3_device_ops dev_ops = {
166     .free = vnet_nic_free,
167     .reset = NULL,
168     .start = NULL,
169     .stop = NULL,
170 };
171
172 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
173     struct vnet_nic_state * vnetnic = NULL;
174     char * name = v3_cfg_val(cfg, "name");
175
176     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
177
178     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
179     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
180
181     struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic);
182
183     if (v3_attach_device(vm, dev) == -1) {
184         PrintError("Could not attach device %s\n", name);
185         return -1;
186     }
187
188     vnetnic->net_ops.send = vnet_send;
189     if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), 
190                            &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
191         PrintError("Could not connect %s to frontend %s\n", 
192                    name, v3_cfg_val(frontend_cfg, "tag"));
193         return -1;
194     }
195
196     if (register_to_vnet(vm, vnetnic, name, vnetnic->mac) == -1) {
197         return -1;
198     }
199
200     PrintDebug("Vnet-nic device %s initialized\n", name);
201
202     return 0;
203 }
204
205 device_register("VNET_NIC", vnet_nic_init)