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) 2010, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2010, 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, Direct Network Bridge
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_dev_mgr.h>
24 #include <palacios/vm_guest_mem.h>
25 #include <palacios/vmm_sprintf.h>
26 #include <interfaces/vmm_packet.h>
28 #ifndef V3_CONFIG_DEBUG_NIC_BRIDGE
30 #define PrintDebug(fmt, args...)
33 struct nic_bridge_state {
34 struct v3_vm_info * vm;
35 struct v3_dev_net_ops net_ops;
36 struct v3_packet * packet_state;
39 static int bridge_send(uint8_t * buf, uint32_t len,
40 void * private_data) {
41 struct nic_bridge_state * bridge = (struct nic_bridge_state *)private_data;
43 #ifdef V3_CONFIG_DEBUG_NIC_BRIDGE
45 PrintDebug(VM_NONE, VCORE_NONE, "NIC Bridge: send pkt size: %d\n", len);
46 v3_hexdump(buf, len, NULL, 0);
50 return v3_packet_send(bridge->packet_state, buf, len);
53 static int packet_input(struct v3_packet * packet_state, uint8_t * pkt, uint32_t size) {
54 struct nic_bridge_state * bridge = (struct nic_bridge_state *)packet_state->guest_packet_data;
56 #ifdef V3_CONFIG_DEBUG_NIC_BRIDGE
58 PrintDebug(VM_NONE, VCORE_NONE, "NIC Bridge: recv pkt size: %d\n", size);
59 v3_hexdump(pkt, size, NULL, 0);
63 return bridge->net_ops.recv(pkt,
65 bridge->net_ops.config.frontend_data);
69 static int nic_bridge_free(struct nic_bridge_state * bridge) {
70 /*TODO: detach from front device */
72 v3_packet_close(bridge->packet_state);
78 static struct v3_device_ops dev_ops = {
79 .free = (int (*)(void *))nic_bridge_free,
83 static int nic_bridge_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
84 struct nic_bridge_state * bridge = NULL;
85 char * dev_id = v3_cfg_val(cfg, "ID");
88 v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
90 v3_cfg_tree_t * hostnic_cfg = v3_cfg_subtree(cfg, "hostnic");
91 host_nic = v3_cfg_val(hostnic_cfg, "name");
92 if(host_nic == NULL) {
96 bridge = (struct nic_bridge_state *)V3_Malloc(sizeof(struct nic_bridge_state));
99 PrintError(vm, VCORE_NONE, "Cannot allocate in init\n");
103 memset(bridge, 0, sizeof(struct nic_bridge_state));
105 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, bridge);
108 PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
113 bridge->net_ops.send = bridge_send;
116 if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"),
117 &(bridge->net_ops), frontend_cfg, bridge) == -1) {
118 PrintError(vm, VCORE_NONE, "Could not connect %s to frontend %s\n",
119 dev_id, v3_cfg_val(frontend_cfg, "tag"));
120 v3_remove_device(dev);
124 PrintDebug(vm, VCORE_NONE, "NIC-Bridge: Connect %s to frontend %s\n",
125 dev_id, v3_cfg_val(frontend_cfg, "tag"));
127 bridge->packet_state = v3_packet_connect(vm, host_nic,
128 bridge->net_ops.config.fnt_mac,
132 if(bridge->packet_state == NULL){
133 PrintError(vm, VCORE_NONE, "NIC-Bridge: Error to connect to host ethernet device\n");
140 device_register("NIC_BRIDGE", nic_bridge_init)