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.


change to device configuration syntax
[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 #include <palacios/vmm_sprintf.h>
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 v3_vm_info * vm;
39     struct v3_dev_net_ops net_ops;
40     int vnet_dev_id;
41 };
42
43
44 static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){
45     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
46
47     struct v3_vnet_pkt pkt;
48     pkt.size = len;
49     pkt.src_type = LINK_INTERFACE;
50     pkt.src_id = vnetnic->vnet_dev_id;
51     memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
52     pkt.data = buf;
53
54 #ifdef CONFIG_DEBUG_VNET_NIC
55     {
56         PrintDebug("Virtio VNET-NIC: send pkt size: %d, pkt src_id: %d\n", 
57                         len,  vnetnic->vnet_dev_id);
58         v3_hexdump(buf, len, NULL, 0);
59     }
60 #endif
61 /*
62     v3_vnet_rx(buf, len, vnetnic->vnet_dev_id, LINK_INTERFACE);
63         
64     //if on the dom0 core, interrupt the domU core to poll pkts
65     //otherwise, call the polling directly
66     int cpu = V3_Get_CPU();
67     cpu = (cpu == 0)?1:0;
68     v3_interrupt_cpu(vnetnic->vm, cpu, V3_VNET_POLLING_VECTOR);
69  */
70  
71     v3_vnet_send_pkt(&pkt, NULL);
72
73     return 0;
74 }
75
76 static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void * private_data){
77     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
78         
79     PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic);     
80
81     return vnetnic->net_ops.recv(pkt->data, pkt->size, vnetnic->net_ops.frontend_data);
82 }
83
84 static int register_to_vnet(struct v3_vm_info * vm,
85                      struct vnet_nic_state *vnet_nic,
86                      char *dev_name,
87                      uchar_t mac[6]) { 
88    
89     PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic);
90         
91     return v3_vnet_add_dev(vm, mac, virtio_input, (void *)vnet_nic);
92 }
93
94 static int vnet_nic_free(struct vm_device * dev) {
95     return 0;
96 }
97
98 static struct v3_device_ops dev_ops = {
99     .free = vnet_nic_free,
100     .reset = NULL,
101     .start = NULL,
102     .stop = NULL,
103 };
104
105
106 static int str2mac(char *macstr, char mac[6]){
107     char hex[2], *s = macstr;
108     int i = 0;
109
110     while(s){
111         memcpy(hex, s, 2);
112         mac[i++] = (char)atox(hex);
113         if (i == 6) return 0;
114         s=strchr(s, ':');
115         if(s) s++;
116     }
117
118     return -1;
119 }
120
121 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
122     struct vnet_nic_state * vnetnic = NULL;
123     char * dev_id = v3_cfg_val(cfg, "ID");
124     char * macstr = NULL;
125     char mac[6];
126     int vnet_dev_id = 0;
127
128     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
129     macstr = v3_cfg_val(frontend_cfg, "mac");
130
131     if (macstr == NULL) {
132         PrintDebug("Vnet-nic: No Mac specified\n");
133     } else {
134         str2mac(macstr, mac);
135     }
136
137     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
138     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
139
140     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, vnetnic);
141
142     if (v3_attach_device(vm, dev) == -1) {
143         PrintError("Could not attach device %s\n", dev_id);
144         return -1;
145     }
146
147     vnetnic->net_ops.send = vnet_send;
148     memcpy(vnetnic->mac, mac, 6);
149     vnetnic->vm = vm;
150         
151     if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), 
152                            &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
153         PrintError("Could not connect %s to frontend %s\n", 
154                    dev_id, v3_cfg_val(frontend_cfg, "tag"));
155         return -1;
156     }
157
158     PrintDebug("Vnet-nic: Connect %s to frontend %s\n", 
159                    dev_id, v3_cfg_val(frontend_cfg, "tag"));
160
161     if ((vnet_dev_id = register_to_vnet(vm, vnetnic, dev_id, vnetnic->mac)) == -1) {
162         PrintError("Vnet-nic device %s (mac: %s) fails to registered to VNET\n", dev_id, macstr);
163     }
164     vnetnic->vnet_dev_id = vnet_dev_id;
165
166     PrintDebug("Vnet-nic device %s (mac: %s, %ld) registered to VNET\n", dev_id, macstr, *((ulong_t *)vnetnic->mac));
167
168
169 //for temporary hack for vnet bridge test
170 #if 1
171     {
172         uchar_t zeromac[6] = {0,0,0,0,0,0};
173                 
174         if(!strcmp(dev_id, "vnet_nic")){
175             struct v3_vnet_route route;
176                 
177             route.dst_id = vnet_dev_id;
178             route.dst_type = LINK_INTERFACE;
179             route.src_id = 0;
180             route.src_type = LINK_EDGE;
181             memcpy(route.dst_mac, zeromac, 6);
182             route.dst_mac_qual = MAC_ANY;
183             memcpy(route.src_mac, zeromac, 6);
184             route.src_mac_qual = MAC_ANY;  
185             v3_vnet_add_route(route);
186
187
188             route.dst_id = 0;
189             route.dst_type = LINK_EDGE;
190             route.src_id = vnet_dev_id;
191             route.src_type = LINK_INTERFACE;
192             memcpy(route.dst_mac, zeromac, 6);
193             route.dst_mac_qual = MAC_ANY;
194             memcpy(route.src_mac, zeromac, 6);
195             route.src_mac_qual = MAC_ANY;
196
197             v3_vnet_add_route(route);
198         }
199     }
200 #endif
201
202 //for temporary hack for Linux bridge (w/o encapuslation) test
203 #if 0
204     {
205         static int vnet_nic_guestid = -1;
206         static int vnet_nic_dom0 = -1;
207         uchar_t zeromac[6] = {0,0,0,0,0,0};
208                 
209         if(!strcmp(dev_id, "vnet_nic")){ //domu
210             vnet_nic_guestid = vnet_dev_id;
211         }
212         if (!strcmp(dev_id, "vnet_nic_dom0")){
213             vnet_nic_dom0 = vnet_dev_id;
214         }\r
215
216         if(vnet_nic_guestid != -1 && vnet_nic_dom0 !=-1){
217             struct v3_vnet_route route;
218                 
219             route.src_id = vnet_nic_guestid;
220             route.src_type = LINK_INTERFACE;
221             route.dst_id = vnet_nic_dom0;
222             route.dst_type = LINK_INTERFACE;
223             memcpy(route.dst_mac, zeromac, 6);
224             route.dst_mac_qual = MAC_ANY;
225             memcpy(route.src_mac, zeromac, 6);
226             route.src_mac_qual = MAC_ANY;  
227             v3_vnet_add_route(route);
228
229
230             route.src_id = vnet_nic_dom0;
231             route.src_type = LINK_INTERFACE;
232             route.dst_id = vnet_nic_guestid;
233             route.dst_type = LINK_INTERFACE;
234             memcpy(route.dst_mac, zeromac, 6);
235             route.dst_mac_qual = MAC_ANY;
236             memcpy(route.src_mac, zeromac, 6);
237             route.src_mac_qual = MAC_ANY;
238
239             v3_vnet_add_route(route);
240         }
241     }
242 #endif
243
244     return 0;
245 }
246
247 device_register("VNET_NIC", vnet_nic_init)