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;
46 struct list_head node;
49 struct vnet_brg_state {
52 struct list_head link_list;
55 sock_type_t serv_sock_type;
58 /* The thread recving pkts from sockets. */
63 unsigned long pkt_sent, pkt_recv, pkt_drop;
66 static struct vnet_brg_state lnxbrg_state;
68 static int vnet_lnxbrg_reset(struct vnet_brg_state * state) {
69 memset(state, 0, sizeof(struct vnet_brg_state));
72 state->serv_sock = -1;
73 state->serv_port = vnet_udp_port;
74 state->serv_sock_type = SOCK_UDP;
76 if(v3_lock_init(&(state->lock)) < 0){
77 PrintError("VNET Linux Bridge: error to initiate vnet lock\n");
84 struct vnet_link * link_by_ip(struct vnet_brg_state * state, uint32_t ip) {
85 struct vnet_link * link = NULL;
87 list_for_each_entry(link, &(state->link_list), node) {
88 if (link->dst_ip == ip) {
96 struct vnet_link * link_by_idx(struct vnet_brg_state * state, int idx) {
97 struct vnet_link * link = NULL;
99 list_for_each_entry(link, &(state->link_list), node) {
100 if (link->link_idx == idx) {
108 udp_send(int sockid, uint32_t dst_ip,
109 uint16_t dst_port, uchar_t * pkt,
111 if(dst_ip > 0 && dst_port > 0){
112 return V3_SendTo_IP(sockid, dst_ip, dst_port, pkt, len);
115 return V3_Send(sockid, pkt, len);
120 udp_recv(int sockid, uint32_t * src_ip,
121 uint16_t * src_port, uchar_t *buf,
124 return V3_Recv(sockid, buf, len);
130 brg_send(struct vnet_brg_state * state,
131 struct v3_vm_info * vm,
132 struct v3_vnet_pkt * vnet_pkt,
133 void * private_data){
134 struct vnet_link * link = NULL;
136 #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
138 PrintDebug("vnet_brg_send... pkt size: %d, link: %d, struct len: %d\n",
141 sizeof(struct v3_vnet_pkt));
146 link = link_by_idx(vnet_pkt->dst_id);
148 if(link->type == SOCK_TCP){
150 }else if(link->type == SOCK_UDP){
151 udp_send(link->socket, 0, 0, vnet_pkt->data, vnet_pkt->size);
154 PrintError("VNET Linux Bridge: wrong link type\n");
158 PrintDebug("VNET Linux Bridge: wrong dst link, idx: %d, discards the packet\n", vnet_pkt->dst_id);
166 static int init_serv(struct vnet_brg_state * state) {
169 if(state->serv_sock_type == SOCK_UDP){
170 sock = V3_Create_UDP_Socket();
172 PrintError("Could not create socket, Initiate VNET server error\n");
176 err = V3_Bind_Socket(sock, state->serv_port);
178 PrintError("Error to bind VNET Linux bridge receiving UDP socket\n");
181 state->serv_sock = sock;
187 static int vnet_server(void * arg) {
188 struct v3_vnet_pkt pkt;
189 struct vnet_link *link;
190 struct vnet_brg_state * state = (struct vnet_brg_state *)arg;
191 uchar_t buf[ETHERNET_MTU];
197 len = udp_recv(state->serv_sock, &ip, &port, buf, ETHERNET_MTU);
199 PrintError("VNET Linux Bridge: receive error\n");
203 link = link_by_ip(ip);
205 pkt.src_id= link->link_idx;
212 pkt.src_type = LINK_EDGE;
213 memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
216 #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE
218 PrintDebug("VNET Linux Bridge: recv pkt size: %d, pkt src_id: %d\n",
220 v3_hexdump(buf, len, NULL, 0);
224 v3_vnet_send_pkt(&pkt, NULL);
233 static int vnet_lnxbrg_init() {
234 struct v3_vnet_bridge_ops brg_ops;
235 struct vnet_brg_state * state;
237 state = (struct vnet_brg_state *)V3_Malloc(sizeof(struct vnet_brg_state));
238 V3_ASSERT(state != NULL);
240 vnet_lnxbrg_reset(state);
242 brg_ops.input = brg_send;
244 v3_vnet_add_bridge(NULL, &brg_ops, state);
247 V3_CREATE_THREAD(vnet_server, state, "VNET_LNX_BRIDGE");
249 PrintDebug("VNET Linux Bridge initiated\n");
255 device_register("LNX_VNET_BRIDGE", vnet_lnxbrg_init)