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.


format fixes
[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     struct v3_vnet_pkt pkt;
47
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                             uint8_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, uint8_t mac[6]){
107     uint8_t hex[2];
108     int i = 0;
109     char * s = macstr;
110
111     while (s) {
112         memcpy(hex, s, 2);
113         mac[i++] = (char)atox(hex);
114
115         if (i == 6) {
116             return 0;
117         }
118
119         s = strchr(s, ':');
120
121         if (s) {
122             s++;
123         }
124     }
125
126     return -1;
127 }
128
129 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
130     struct vnet_nic_state * vnetnic = NULL;
131     char * dev_id = v3_cfg_val(cfg, "ID");
132     char * macstr = NULL;
133     int vnet_dev_id = 0;
134     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
135
136     macstr = v3_cfg_val(frontend_cfg, "mac");
137
138     if (macstr == NULL) {
139         PrintDebug("Vnet-nic configuration error: No Mac specified\n");
140         return -1;
141     }
142
143     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
144     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
145
146     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, vnetnic);
147
148     if (v3_attach_device(vm, dev) == -1) {
149         PrintError("Could not attach device %s\n", dev_id);
150         return -1;
151     }
152
153
154
155     vnetnic->net_ops.send = vnet_send;
156     str2mac(macstr, vnetnic->mac);
157     vnetnic->vm = vm;
158         
159     if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), 
160                            &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
161         PrintError("Could not connect %s to frontend %s\n", 
162                    dev_id, v3_cfg_val(frontend_cfg, "tag"));
163         return -1;
164     }
165
166     PrintDebug("Vnet-nic: Connect %s to frontend %s\n", 
167                dev_id, v3_cfg_val(frontend_cfg, "tag"));
168
169     if ((vnet_dev_id = register_to_vnet(vm, vnetnic, dev_id, vnetnic->mac)) == -1) {
170         PrintError("Vnet-nic device %s (mac: %s) fails to registered to VNET\n", dev_id, macstr);
171         return -1;
172     }
173
174     vnetnic->vnet_dev_id = vnet_dev_id;
175
176     PrintDebug("Vnet-nic device %s (mac: %s, %ld) registered to VNET\n", dev_id, macstr, *((uint32_t *)vnetnic->mac));
177
178
179     return 0;
180 }
181
182 device_register("VNET_NIC", vnet_nic_init)