--- /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@cs.northwestern.edu>
+ * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Lei Xia <lxia@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+ 
+ /* VNET backend bridge for Linux host
+ */
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_vnet.h>
+#include <palacios/vmm_sprintf.h>
+#include <palacios/vmm_socket.h>
+
+#ifndef CONFIG_DEBUG_VNET_LNX_BRIGE
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+typedef enum {SOCK_UDP, SOCK_TCP, SOCK_OTHER} sock_type_t; 
+
+const uint16_t vnet_udp_port = 20003;
+
+struct vnet_link {
+    uint32_t dst_ip;
+    uint16_t dst_port;
+    
+    int socket;
+    sock_type_t type;
+    int link_idx;
+
+    struct list_head node;
+};
+
+struct vnet_brg_state {
+    uint32_t num_links; 
+
+    struct list_head link_list;
+
+    int serv_sock;
+    sock_type_t serv_sock_type;
+    int serv_port;
+    
+    /* The thread recving pkts from sockets. */
+    int serv_thread;
+
+    v3_lock_t lock;
+
+    unsigned long pkt_sent, pkt_recv, pkt_drop;
+};
+
+static struct vnet_brg_state lnxbrg_state;
+
+static int vnet_lnxbrg_reset(struct vnet_brg_state * state) {
+    memset(state, 0, sizeof(struct vnet_brg_state));
+
+    state->num_links = 0;
+    state->serv_sock = -1;
+    state->serv_port = vnet_udp_port;
+    state->serv_sock_type = SOCK_UDP;
+
+    if(v3_lock_init(&(state->lock)) < 0){
+       PrintError("VNET Linux Bridge: error to initiate vnet lock\n");
+    }
+
+    return 0;
+}
+
+
+struct vnet_link * link_by_ip(struct vnet_brg_state * state, uint32_t ip) {
+    struct vnet_link * link = NULL;
+
+    list_for_each_entry(link, &(state->link_list), node) {
+       if (link->dst_ip == ip) {
+           return link;
+       }
+    }
+
+    return NULL;
+}
+
+struct vnet_link * link_by_idx(struct vnet_brg_state * state, int idx) {
+    struct vnet_link * link = NULL;
+
+    list_for_each_entry(link, &(state->link_list), node) {
+       if (link->link_idx == idx) {
+           return link;
+       }
+    }
+    return NULL;
+}
+
+static int
+udp_send(int sockid, uint32_t dst_ip, 
+                       uint16_t dst_port, uchar_t * pkt, 
+                       uint16_t len){
+    if(dst_ip > 0 && dst_port > 0){
+       return V3_SendTo_IP(sockid, dst_ip, dst_port, pkt, len);
+    }
+
+    return V3_Send(sockid, pkt, len);
+}
+
+
+static int 
+udp_recv(int sockid, uint32_t * src_ip, 
+                       uint16_t * src_port, uchar_t *buf, 
+                       uint16_t len) {
+
+    return V3_Recv(sockid, buf, len);
+}
+
+
+
+static int 
+brg_send(struct vnet_brg_state * state,
+                       struct v3_vm_info * vm,  
+                       struct v3_vnet_pkt * vnet_pkt, 
+                       void * private_data){
+    struct vnet_link * link = NULL;
+       
+    #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
+    {
+       PrintDebug("vnet_brg_send... pkt size: %d, link: %d, struct len: %d\n",
+                       vnet_pkt->size,
+                       vnet_pkt->dst_id,
+                       sizeof(struct v3_vnet_pkt));
+    }
+    #endif
+
+    state->pkt_recv ++;
+    link = link_by_idx(vnet_pkt->dst_id);
+    if (link != NULL) {
+       if(link->type == SOCK_TCP){
+               
+       }else if(link->type == SOCK_UDP){
+           udp_send(link->socket, 0, 0, vnet_pkt->data, vnet_pkt->size);
+           state->pkt_sent ++;
+       }else {
+           PrintError("VNET Linux Bridge: wrong link type\n"); 
+           return -1;
+       }
+    } else {
+       PrintDebug("VNET Linux Bridge: wrong dst link, idx: %d, discards the packet\n", vnet_pkt->dst_id);
+       state->pkt_drop ++;
+    }
+
+    return 0;
+}
+
+
+static int init_serv(struct vnet_brg_state * state) {
+    int sock, err;
+
+    if(state->serv_sock_type == SOCK_UDP){
+       sock = V3_Create_UDP_Socket();
+       if (sock < 0) {
+           PrintError("Could not create socket, Initiate VNET server error\n");
+           return -1;
+       }
+
+       err = V3_Bind_Socket(sock, state->serv_port);
+       if(err < 0){
+           PrintError("Error to bind VNET Linux bridge receiving UDP socket\n");
+           return -1;
+       }
+       state->serv_sock = sock;
+    }
+
+    return 0;
+}
+
+static int vnet_server(void * arg) {
+    struct v3_vnet_pkt pkt;
+    struct vnet_link *link;
+    struct vnet_brg_state * state = (struct vnet_brg_state *)arg;
+    uchar_t buf[ETHERNET_MTU];
+    uint32_t ip = 0;
+    uint16_t port = 0;
+    int len;
+
+    while (1) {
+       len = udp_recv(state->serv_sock, &ip, &port, buf, ETHERNET_MTU);
+       if(len < 0) {
+           PrintError("VNET Linux Bridge: receive error\n");
+           continue;
+       }
+
+       link = link_by_ip(ip);
+       if (link != NULL) {
+           pkt.src_id= link->link_idx;
+       }
+       else { 
+           pkt.src_id= -1;
+       }
+
+       pkt.size = len;
+       pkt.src_type = LINK_EDGE;
+       memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
+       pkt.data = buf;
+       
+       #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
+       {
+           PrintDebug("VNET Linux Bridge: recv pkt size: %d, pkt src_id: %d\n", 
+                       len,  pkt.src_id);
+           v3_hexdump(buf, len, NULL, 0);
+       }
+       #endif
+
+       v3_vnet_send_pkt(&pkt, NULL);
+       
+       state->pkt_recv ++;
+    }
+
+    return 0;
+}
+
+
+static int vnet_lnxbrg_init() {
+    struct v3_vnet_bridge_ops brg_ops;
+    struct vnet_brg_state * state;
+       
+    state = (struct vnet_brg_state *)V3_Malloc(sizeof(struct vnet_brg_state));
+    V3_ASSERT(state != NULL);
+
+    vnet_lnxbrg_reset(state);
+
+    brg_ops.input = brg_send;
+
+    v3_vnet_add_bridge(NULL, &brg_ops, state);
+
+    init_serv();
+    V3_CREATE_THREAD(vnet_server, state, "VNET_LNX_BRIDGE");
+
+    PrintDebug("VNET Linux Bridge initiated\n");
+
+    return 0;
+}
+
+
+device_register("LNX_VNET_BRIDGE", vnet_lnxbrg_init)