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.


86f5ba7c98969c4f55098216557061d9f7ee17e6
[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 v3_vnet_pkt pkt;
46     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
47
48
49     pkt.size = len;
50     pkt.src_type = LINK_INTERFACE;
51     pkt.src_id = vnetnic->vnet_dev_id;
52     memcpy(pkt.data, buf, pkt.size);
53
54 #ifdef CONFIG_DEBUG_VNET_NIC
55     {
56         PrintDebug("Virtio VNET-NIC: send pkt size: %d, pkt src_id: %d, src_type: %d\n", 
57                         len, pkt.src_id, pkt.src_type);
58         v3_hexdump(buf, len, NULL, 0);
59     }
60 #endif
61
62
63     v3_vnet_send_pkt(&pkt, NULL);
64
65     return 0;
66 }
67
68 static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void * private_data){
69     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
70         
71     PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic);     
72
73     return vnetnic->net_ops.recv(pkt->data, pkt->size, vnetnic->net_ops.frontend_data);
74 }
75
76 static int register_to_vnet(struct v3_vm_info * vm,
77                      struct vnet_nic_state *vnet_nic,
78                      char *dev_name,
79                      uchar_t mac[6]) { 
80    
81     PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic);
82         
83     return v3_vnet_add_dev(vm, mac, virtio_input, (void *)vnet_nic);
84 }
85
86 static int vnet_nic_free(struct vm_device * dev) {
87     return 0;
88 }
89
90 static struct v3_device_ops dev_ops = {
91     .free = vnet_nic_free,
92     .reset = NULL,
93     .start = NULL,
94     .stop = NULL,
95 };
96
97
98 static int str2mac(char *macstr, char mac[6]){
99     char hex[2], *s = macstr;
100     int i = 0;
101
102     while(s){
103         memcpy(hex, s, 2);
104         mac[i++] = (char)atox(hex);
105         if (i == 6) return 0;
106         s=strchr(s, ':');
107         if(s) s++;
108     }
109
110     return -1;
111 }
112
113 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
114     struct vnet_nic_state * vnetnic = NULL;
115     char * name = v3_cfg_val(cfg, "name");
116     char * macstr = NULL;
117     char mac[6];
118     int vnet_dev_id;
119
120     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
121     macstr = v3_cfg_val(frontend_cfg, "mac");
122
123     if (macstr == NULL) {
124         PrintDebug("Vnet-nic: No Mac specified\n");
125     } else {
126         str2mac(macstr, mac);
127     }
128
129     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
130     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
131
132     struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic);
133
134     if (v3_attach_device(vm, dev) == -1) {
135         PrintError("Could not attach device %s\n", name);
136         return -1;
137     }
138
139     vnetnic->net_ops.send = vnet_send;
140     memcpy(vnetnic->mac, mac, 6);
141     vnetnic->vm = vm;
142         
143     if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), 
144                            &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
145         PrintError("Could not connect %s to frontend %s\n", 
146                    name, v3_cfg_val(frontend_cfg, "tag"));
147         return -1;
148     }
149
150     PrintDebug("Vnet-nic: Connect %s to frontend %s\n", 
151                    name, v3_cfg_val(frontend_cfg, "tag"));
152
153     if ((vnet_dev_id = register_to_vnet(vm, vnetnic, name, vnetnic->mac)) == -1) {
154         PrintError("Vnet-nic device %s (mac: %s) fails to registered to VNET\n", name, macstr);
155     }
156     vnetnic->vnet_dev_id = vnet_dev_id;
157
158     PrintDebug("Vnet-nic device %s (mac: %s, %ld) registered to VNET\n", name, macstr, *((ulong_t *)vnetnic->mac));
159
160
161 //for temporary hack for vnet bridge test
162 #if 1
163     {
164         uchar_t zeromac[6] = {0,0,0,0,0,0};
165                 
166         if(!strcmp(name, "vnet_nic")){
167             struct v3_vnet_route route;
168                 
169             route.dst_id = vnet_dev_id;
170             route.dst_type = LINK_INTERFACE;
171             route.src_id = 0;
172             route.src_type = LINK_EDGE;
173             memcpy(route.dst_mac, zeromac, 6);
174             route.dst_mac_qual = MAC_ANY;
175             memcpy(route.src_mac, zeromac, 6);
176             route.src_mac_qual = MAC_ANY;  
177             v3_vnet_add_route(route);
178
179
180             route.dst_id = 0;
181             route.dst_type = LINK_EDGE;
182             route.src_id = vnet_dev_id;
183             route.src_type = LINK_INTERFACE;
184             memcpy(route.dst_mac, zeromac, 6);
185             route.dst_mac_qual = MAC_ANY;
186             memcpy(route.src_mac, zeromac, 6);
187             route.src_mac_qual = MAC_ANY;
188
189             v3_vnet_add_route(route);
190         }
191     }
192 #endif
193
194     return 0;
195 }
196
197 device_register("VNET_NIC", vnet_nic_init)