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.


6a6406c7c7ab6550e944b55b11a258f8ad1c08a9
[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) 2010, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2010, 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 #include <palacios/vmm_ethernet.h>
30
31 #ifndef CONFIG_DEBUG_VNET_NIC
32 #undef PrintDebug
33 #define PrintDebug(fmt, args...)
34 #endif
35
36
37 struct vnet_nic_state {
38     struct v3_vm_info * vm;
39     struct v3_dev_net_ops net_ops;
40     int vnet_dev_id;
41 };
42
43 /* called by frontend device, 
44   * tell the VNET can start sending pkt to it */
45 static void start_rx(void * private_data){
46     //struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
47
48     //v3_vnet_enable_device(vnetnic->vnet_dev_id);
49 }
50
51 /* called by frontend device, 
52   * tell the VNET stop sending pkt to it */
53 static void stop_rx(void * private_data){
54     //struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
55
56     //v3_vnet_disable_device(vnetnic->vnet_dev_id);
57 }
58
59 /* called by frontend, send pkt to VNET */
60 static int vnet_nic_send(uint8_t * buf, uint32_t len, 
61                          void * private_data) {
62     struct vnet_nic_state * vnetnic = (struct vnet_nic_state *)private_data;
63
64     struct v3_vnet_pkt pkt;
65     pkt.size = len;
66     pkt.src_type = LINK_INTERFACE;
67     pkt.src_id = vnetnic->vnet_dev_id;
68     memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
69     pkt.data = buf;
70
71 #ifdef CONFIG_DEBUG_VNET_NIC
72     {
73         PrintDebug("VNET-NIC: send pkt (size: %d, src_id: %d, src_type: %d)\n", 
74                    pkt.size, pkt.src_id, pkt.src_type);
75         v3_hexdump(buf, len, NULL, 0);
76     }
77 #endif
78
79     return v3_vnet_send_pkt(&pkt, NULL);;
80 }
81
82
83 /* send pkt to frontend device */
84 static int virtio_input(struct v3_vm_info * info, 
85                         struct v3_vnet_pkt * pkt, 
86                         void * private_data){
87     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
88
89     PrintDebug("VNET-NIC: receive pkt (size %d, src_id:%d, src_type: %d, dst_id: %d, dst_type: %d)\n", 
90                 pkt->size, pkt->src_id, pkt->src_type, pkt->dst_id, pkt->dst_type);
91         
92     return vnetnic->net_ops.recv(pkt->data, pkt->size,
93                                  vnetnic->net_ops.frontend_data);
94 }
95
96 /* tell frontend device to poll data from guest */
97 static void virtio_poll(struct v3_vm_info * info, 
98                         void * private_data){
99     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
100
101     vnetnic->net_ops.poll(info, vnetnic->net_ops.frontend_data);
102 }
103
104
105 /* notify the frontend to start sending pkt to VNET*/
106 static void start_tx(void * private_data){
107     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
108
109     vnetnic->net_ops.start_tx(vnetnic->net_ops.frontend_data);
110 }
111
112 /* notify the frontend device to stop sending pkt to VNET*/
113 static void stop_tx(void * private_data){
114     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
115
116     vnetnic->net_ops.stop_tx(vnetnic->net_ops.frontend_data);
117 }
118
119
120 static int vnet_nic_free(struct vnet_nic_state * vnetnic) {
121
122     v3_vnet_del_dev(vnetnic->vnet_dev_id);
123     V3_Free(vnetnic);
124         
125     return 0;
126 }
127
128 static struct v3_device_ops dev_ops = {
129     .free = (int (*)(void *))vnet_nic_free,
130
131 };
132
133 static struct v3_vnet_dev_ops vnet_dev_ops = {
134     .input = virtio_input,
135     .poll = virtio_poll,
136     .start_tx = start_tx,
137     .stop_tx = stop_tx,
138 };
139
140
141 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
142     struct vnet_nic_state * vnetnic = NULL;
143     char * dev_id = v3_cfg_val(cfg, "ID");
144     int vnet_dev_id;
145
146     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
147
148     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
149     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
150
151     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vnetnic);
152     if (dev == NULL) {
153         PrintError("Could not attach device %s\n", dev_id);
154         V3_Free(vnetnic);
155         return -1;
156     }
157
158     vnetnic->net_ops.send = vnet_nic_send;
159     vnetnic->net_ops.start_rx = start_rx;
160     vnetnic->net_ops.stop_rx = stop_rx;
161     vnetnic->vm = vm;
162         
163     if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), 
164                            &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
165         PrintError("Could not connect %s to frontend %s\n", 
166                    dev_id, v3_cfg_val(frontend_cfg, "tag"));
167         v3_remove_device(dev);
168         return -1;
169     }
170
171     PrintDebug("Vnet-nic: Connect %s to frontend %s\n", 
172               dev_id, v3_cfg_val(frontend_cfg, "tag"));
173
174     if ((vnet_dev_id = v3_vnet_add_dev(vm, vnetnic->net_ops.fnt_mac, &vnet_dev_ops, (void *)vnetnic)) == -1) {
175         PrintError("Vnet-nic device %s fails to registered to VNET\n", dev_id);
176         v3_remove_device(dev);
177         return 0;
178     }
179     vnetnic->vnet_dev_id = vnet_dev_id;
180
181     PrintDebug("Vnet-nic device %s registered to VNET\n", dev_id);
182
183     return 0;
184 }
185
186 device_register("VNET_NIC", vnet_nic_init)