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@cs.northwestern.edu>
11 * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Lei Xia <lxia@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 /* VNET backend bridge for Linux host
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_dev_mgr.h>
24 #include <palacios/vm_guest_mem.h>
25 #include <palacios/vmm_vnet.h>
26 #include <palacios/vmm_sprintf.h>
27 #include <palacios/vmm_socket.h>
29 #ifndef CONFIG_DEBUG_VNET_LNX_BRIGE
31 #define PrintDebug(fmt, args...)
34 typedef enum {SOCK_UDP, SOCK_TCP, SOCK_OTHER} sock_type_t;
36 const uint16_t vnet_udp_port = 20003;
47 struct list_head node;
50 struct vnet_brg_state {
52 struct list_head link_list;
55 sock_type_t serv_sock_type;
60 unsigned long pkt_sent, pkt_recv, pkt_drop;
64 static int vnet_lnxbrg_reset(struct vnet_brg_state * state) {
65 memset(state, 0, sizeof(struct vnet_brg_state));
68 state->serv_sock = -1;
69 state->serv_port = vnet_udp_port;
70 state->serv_sock_type = SOCK_UDP;
72 if(v3_lock_init(&(state->lock)) < 0){
73 PrintError("VNET Linux Bridge: error to initiate vnet lock\n");
80 struct vnet_link * link_by_ip(struct vnet_brg_state * state, uint32_t ip) {
81 struct vnet_link * link = NULL;
83 list_for_each_entry(link, &(state->link_list), node) {
84 if (link->dst_ip == ip) {
92 struct vnet_link * link_by_idx(struct vnet_brg_state * state, int idx) {
93 struct vnet_link * link = NULL;
95 list_for_each_entry(link, &(state->link_list), node) {
96 if (link->link_idx == idx) {
104 udp_send(int sockid, uint32_t dst_ip,
105 uint16_t dst_port, uchar_t * pkt,
107 if(dst_ip > 0 && dst_port > 0){
108 return V3_SendTo_IP(sockid, dst_ip, dst_port, pkt, len);
111 return V3_Send(sockid, pkt, len);
116 udp_recv(int sockid, uint32_t * src_ip,
117 uint16_t * src_port, uchar_t *buf,
120 return V3_Recv(sockid, buf, len);
126 brg_send( struct v3_vm_info * vm,
127 struct v3_vnet_pkt * vnet_pkt,
128 void * private_data){
129 struct vnet_brg_state * state = (struct vnet_brg_state *)private_data;
130 struct vnet_link * link = NULL;
132 #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
134 PrintDebug("vnet_brg_send... pkt size: %d, link: %d, struct len: %d\n",
137 sizeof(struct v3_vnet_pkt));
142 link = link_by_idx(state, vnet_pkt->dst_id);
144 if(link->type == SOCK_UDP){
145 udp_send(link->socket, 0, 0, vnet_pkt->data, vnet_pkt->size);
148 PrintError("VNET Linux Bridge: wrong link type\n");
152 PrintDebug("VNET Linux Bridge: wrong dst link, idx: %d, discards the packet\n", vnet_pkt->dst_id);
160 static int init_serv(struct vnet_brg_state * state) {
163 if(state->serv_sock_type == SOCK_UDP){
164 sock = V3_Create_UDP_Socket();
166 PrintError("Could not create socket, Initiate VNET server error\n");
170 err = V3_Bind_Socket(sock, state->serv_port);
172 PrintError("Error to bind VNET Linux bridge receiving UDP socket\n");
175 state->serv_sock = sock;
181 static int vnet_server(void * arg) {
182 struct v3_vnet_pkt pkt;
183 struct vnet_link *link;
184 struct vnet_brg_state * state = (struct vnet_brg_state *)arg;
185 uchar_t buf[ETHERNET_MTU];
191 len = udp_recv(state->serv_sock, &ip, &port, buf, ETHERNET_MTU);
193 PrintError("VNET Linux Bridge: receive error\n");
197 link = link_by_ip(state, ip);
199 pkt.src_id= link->link_idx;
206 pkt.src_type = LINK_EDGE;
207 memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
210 #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
212 PrintDebug("VNET Linux Bridge: recv pkt size: %d, pkt src_id: %d\n",
214 v3_hexdump(buf, len, NULL, 0);
218 v3_vnet_send_pkt(&pkt, NULL);
227 static int vnet_lnxbrg_init() {
228 struct v3_vnet_bridge_ops brg_ops;
229 struct vnet_brg_state * state;
231 state = (struct vnet_brg_state *)V3_Malloc(sizeof(struct vnet_brg_state));
232 V3_ASSERT(state != NULL);
234 vnet_lnxbrg_reset(state);
236 brg_ops.input = brg_send;
238 v3_vnet_add_bridge(NULL, &brg_ops, state);
241 V3_CREATE_THREAD(vnet_server, state, "VNET_LNX_BRIDGE");
243 PrintDebug("VNET Linux Bridge initiated\n");
249 device_register("LNX_VNET_BRIDGE", vnet_lnxbrg_init)