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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Lei Xia <lxia@northwestern.edu>
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 //backend device for Virtio NIC
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>
29 struct vnet_nic_state {
35 //used when virtio_nic get a packet from guest and send it to the backend
36 // send packet to all of the virtio nic devices other than the sender
37 static int send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){
38 PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data);
40 v3_vnet_send_rawpkt(buf, len, private_data);
44 static int receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev){
50 static struct v3_dev_net_ops net_ops = {
57 static int input(struct v3_vm_info *info, uchar_t * buf, uint_t len, void * private_data){
58 PrintDebug("Virito NIC: In virtio_input: guest net state %p\n", private_data);
60 return __virtio_dev_send(buf, len, private_data);
64 //register a virtio device to the vnet as backend
65 void register_to_vnet(struct vm_device *dev,
68 struct virtio_net_state * net_state;
69 struct virtio_dev_state *virtio_state = (struct virtio_dev_state *)dev->private_data;
70 uchar_t tapmac[6] = {0x00,0x02,0x55,0x67,0x42,0x39}; //for Intel-VT test HW
71 //uchar_t tapmac[6] = {0x6e,0xa8,0x75,0xf4,0x82,0x95};
72 uchar_t dstmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
73 uchar_t zeromac[6] = {0,0,0,0,0,0};
76 net_state = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
77 memset(net_state, 0, sizeof(struct virtio_net_state));
78 net_state->net_ops = (struct v3_dev_net_ops *)V3_Malloc(sizeof(struct v3_dev_net_ops));
79 net_state->net_ops->send = &vnet_send;
80 net_state->net_ops->receive = &vnet_receive;
83 register_dev(virtio_state, net_state);
85 PrintDebug("Virtio NIC register Device %s: queue size: %d, %d\n", dev->name,
86 net_state->rx_vq.queue_size, net_state->tx_vq.queue_size);
87 PrintDebug("Virtio NIC: connect virtio device %s, state %p, to vnet\n", dev->name, net_state);
89 int idx = vnet_register_device(dev, dev_name, mac, &virtio_input, net_state);
90 //vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
91 if (!strcmp(dev_name, "net_virtiodom0")){
92 vnet_add_route_entry(zeromac, tapmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
93 vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
95 if (!strcmp(dev_name, "net_virtio"))
96 vnet_add_route_entry(tapmac, zeromac, MAC_NONE, MAC_ANY, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
99 v3_vnet_add_node(dev_name, mac, input, priv_data);
100 struct v3_vnet_route route;
102 memset(&route, 0, sizeof(struct v3_vnet_route));
103 memcpy(&route.dest_mac, mac, 6);
104 route.src_mac_qual = MAC_ANY;
105 route.dest_mac_qual = MAC_NONE;
106 route.link_idx = idx;
107 route.link_type = LINK_EDGE;
108 route.src_link_idx = -1;
109 route.src_type = LINK_ANY;
110 v3_vnet_add_route(&route);
113 memset(&route, 0, sizeof(struct v3_vnet_route));
114 memcpy(&route.dest_mac, mac, 6);
115 route.src_mac_qual = MAC_ANY;
116 route.dest_mac_qual = MAC_NONE;
117 route.link_idx = idx;
118 route.link_type = LINK_EDGE;
119 route.src_link_idx = -1;
120 route.src_type = LINK_ANY;
121 v3_vnet_add_route(&route);
127 *called in svm/vmx handler
128 *iteative handled the unsent packet in incoming packet queues for
129 *all virtio nic devices in this guest
131 int v3_vnetnic_pktprocess(struct guest_info * info)
139 static int vnet_nic_free(struct vm_device * dev) {
143 static struct v3_device_ops dev_ops = {
144 .free = vnet_nic_free,
150 static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
151 struct vnet_nic_state * vnetnic = NULL;
152 char * name = v3_cfg_val(cfg, "name");
154 v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
156 vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
157 memset(vnetnic, 0, sizeof(struct vnet_nic_state));
160 PrintDebug("Registering vnet_nic device at\n");
162 struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic);
164 if (v3_attach_device(vm, dev) == -1) {
165 PrintError("Could not attach device %s\n", name);
169 if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"),
170 &net_ops, frontend_cfg, vnetnic) == -1) {
171 PrintError("Could not connect %s to frontend %s\n",
172 name, v3_cfg_val(frontend_cfg, "tag"));
180 device_register("VNET_NIC", vnet_nic_init)