--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu>
+ * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Lei Xia <lxia@northwestern.edu>
+ *
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+//backend device for Virtio NIC, Direct Network Bridge
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_sprintf.h>
+#include <palacios/vmm_packet.h>
+
+#ifndef CONFIG_DEBUG_NIC_BRIDGE
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+struct nic_bridge_state {
+ struct v3_vm_info * vm;
+ struct v3_dev_net_ops net_ops;
+};
+
+static int bridge_send(uint8_t * buf, uint32_t len,
+ void * private_data, struct vm_device *dev){
+ //struct nic_bridge_state *bridge = (struct nic_bridge_state *)private_data;
+
+#ifdef CONFIG_DEBUG_NIC_BRIDGE
+ {
+ PrintDebug("NIC Bridge: send pkt size: %d\n", len);
+ v3_hexdump(buf, len, NULL, 0);
+ }
+#endif
+
+ return V3_send_raw(buf, len);
+}
+
+
+static int packet_input(struct v3_vm_info * vm,
+ struct v3_packet_event * evt,
+ void * private_data) {
+ struct nic_bridge_state *bridge = (struct nic_bridge_state *)private_data;
+
+ PrintDebug("NIC_BRIDGE: Incoming packet size: %d\n", evt->size);
+
+ return bridge->net_ops.recv(evt->pkt,
+ evt->size,
+ bridge->net_ops.frontend_data);
+}
+
+
+static int vnet_nic_free(struct vm_device * dev) {
+ struct nic_bridge_state * bridge = dev->private_data;
+
+ /*detach from front device */
+
+ V3_Free(bridge);
+
+ return 0;
+}
+
+static struct v3_device_ops dev_ops = {
+ .free = vnet_nic_free,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
+};
+
+static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
+ struct nic_bridge_state * bridge = NULL;
+ char * dev_id = v3_cfg_val(cfg, "ID");
+
+ v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+
+ bridge = (struct nic_bridge_state *)V3_Malloc(sizeof(struct nic_bridge_state));
+ memset(bridge, 0, sizeof(struct nic_bridge_state));
+
+ struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, bridge);
+
+ if (v3_attach_device(vm, dev) == -1) {
+ PrintError("Could not attach device %s\n", dev_id);
+ return -1;
+ }
+
+ bridge->net_ops.send = bridge_send;
+ bridge->vm = vm;
+
+ if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"),
+ &(bridge->net_ops), frontend_cfg, bridge) == -1) {
+ PrintError("Could not connect %s to frontend %s\n",
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
+ return -1;
+ }
+
+ PrintDebug("NIC-Bridge: Connect %s to frontend %s\n",
+ dev_id, v3_cfg_val(frontend_cfg, "tag"));
+
+ v3_hook_host_event(vm, HOST_PACKET_EVT, V3_HOST_EVENT_HANDLER(packet_input), dev);
+
+ return 0;
+}
+
+device_register("NIC_BRIDGE", vnet_nic_init)