Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


updates for user space utilities
[palacios.git] / misc / network_servers / v3_nbd / v3_nbd.cc
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <string>
21 #include <iostream>
22 #include <fstream>
23 #include <stdio.h>
24 #include <sstream>
25
26 #ifdef linux 
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #elif defined(WIN32) && !defined(__CYGWIN__)
31
32 #endif
33
34 #include "vtl.h"
35
36
37 #define DEFAULT_LOG_FILE "./status.log"
38 #define DEFAULT_CONF_FILE "v3_nbd.ini"
39
40
41 #define DEFAULT_PORT 9500
42 #define MAX_STRING_SIZE 1024
43 #define MAX_DISKS 32
44
45 #define LOGFILE_TAG "logfile"
46 #define IP_ADDR_TAG "address"
47 #define PORT_TAG  "port"
48 #define DISKS_TAG "disks"
49
50
51 using namespace std;
52 //using namespace __gnu_cxx;
53
54
55 typedef enum {ISO, RAW} disk_type_t;
56
57 struct disk_info {
58     string filename;
59     string tag;
60     disk_type_t type;
61 };
62
63 // eqstr from vtl (config.h)
64 typedef map<const string, struct disk_info, eqstr> disk_list_t;
65
66 struct nbd_config {
67     unsigned long server_addr;
68     int server_port;
69     disk_list_t disks;
70     int num_disks;
71 };
72
73
74
75 static const int enable_debug = 1;
76 static struct nbd_config g_nbd_conf;
77
78 void usage();
79 int config_nbd(string conf_file_name);
80 int serv_loop(int serv_sock);
81 void setup_disk(string disk_tag);
82
83
84 int __main (int argc, char ** argv);
85
86 #ifdef linux
87
88 int main(int argc, char ** argv) {
89   return __main(argc, argv);
90 }
91
92 #elif WIN32
93
94 void main() {
95   __main(0, NULL);
96 }
97
98 #endif 
99
100 int __main (int argc, char ** argv) {
101   string config_file;
102   int serv_sock;
103   if (argc > 2) {
104     usage();
105     exit(0);
106   }
107
108   if (argc == 2) {
109     config_file = string(argv[1]);
110   } else {
111     config_file = DEFAULT_CONF_FILE;
112   }
113
114  
115   if (config_nbd(config_file) == -1) {
116     cerr << "Configuration Error" << endl;
117     exit(-1);
118   }
119
120   // setup network sockets
121
122   vtl_debug("Starting Server Loop\n");
123   serv_loop(serv_sock);
124
125   return 0;
126 }
127
128
129 #ifdef linux
130 int serv_loop(int serv_sock) {
131   fd_set all_set, read_set;
132   int max_fd = -1;
133   RawEthernetPacket pkt;
134
135   FD_ZERO(&all_set);
136   FD_SET(serv_sock, &all_set);
137   max_fd = serv_sock;
138
139
140   while (1) {
141     int nready = 0;
142     read_set = all_set;
143     nready = select(max_fd + 1, &read_set, NULL, NULL, NULL);
144     
145     
146     if (nready == -1) {
147       if (errno == EINTR) {
148         continue;
149       } else {
150         perror("Select returned error: ");
151         break;
152       }
153     }
154     
155
156     if (FD_ISSET(serv_sock, &read_set)) {
157       //vnet_recv();
158
159
160     }
161   }
162
163   return 0;
164 }
165
166 #elif WIN32
167 int serv_loop(iface_t * iface, SOCK vnet_sock, struct vnet_config * vnet_info) {
168   int ret;
169   RawEthernetPacket pkt;
170   WSANETWORKEVENTS net_events;
171   WSAEVENT events[2];
172   DWORD event_i;
173   
174   events[VNET_EVENT] = WSACreateEvent();
175   
176   WSAEventSelect(vnet_sock, events[VNET_EVENT], FD_READ | FD_CLOSE);
177   events[IF_EVENT] = if_get_event(iface);
178   
179   while (1) {
180     event_i = WSAWaitForMultipleEvents(2, events, false, WSA_INFINITE, false);
181     cout << "Wait returned" << endl;
182     
183     if (event_i == WAIT_FAILED) {
184       cout << "ERROR: " <<   GetLastError() << endl;
185       exit(-1);
186     }
187     event_i -= WAIT_OBJECT_0;
188     
189     if (event_i == VNET_EVENT) {
190       
191       if (WSAEnumNetworkEvents(vnet_sock, events[event_i], &net_events) == SOCKET_ERROR) {
192         cout << "EnumEventsError: " << WSAGetLastError() << endl;
193         exit(-1);
194       }
195       if (net_events.lNetworkEvents & FD_READ) {
196         
197         JRLDBG("Receied VNET Packet\n");
198         // we received data
199         
200         if (vnet_info->link_type == TCP_LINK) {
201           pkt.Unserialize(vnet_sock);
202         } else if (vnet_info->link_type == UDP_LINK) {
203           pkt.UdpUnserialize(vnet_sock);
204         }
205         
206         process_outbound_pkt(&pkt);
207         
208         if_write_pkt(iface, &pkt);
209         
210       } else if (net_events.lNetworkEvents & FD_CLOSE) {
211         CLOSE(vnet_sock);
212         return 0;
213       }
214       
215     }
216   }
217   
218   return 0;
219 }
220 #endif
221
222
223
224 int config_nbd(string conf_file_name) {
225     config_t config_map;
226     
227     if (read_config(conf_file_name, &config_map) != 0) {
228         cerr << "Could not read config file..." << endl;
229         return -1;
230     }
231
232     if (config_map.count(IP_ADDR_TAG) > 0) {
233         g_nbd_conf.server_addr = ToIPAddress(config_map[IP_ADDR_TAG].c_str());
234     } 
235
236     if (config_map.count(PORT_TAG) > 0) {
237         g_nbd_conf.server_port = atoi(config_map[PORT_TAG].c_str());
238     } else {
239         g_nbd_conf.server_port = DEFAULT_PORT;
240     }
241         
242     if (config_map.count(DISKS_TAG) > 0) {
243         istringstream disk_stream(config_map[DISKS_TAG], istringstream::in);
244         string disk_tag;
245         int i = 0;
246         
247         while (disk_stream >> disk_tag) {
248
249             if (i >= MAX_DISKS) {
250                 cerr << "You specified too many disks, truncating..." << endl;
251                 break;
252             }
253             
254             setup_disk(disk_tag);
255
256             i++;
257         }
258         
259         g_nbd_conf.num_disks = i;
260     } else {
261         cerr << "Must specify a set of disks" << endl;
262         return -1;
263     }
264     
265     
266     if (config_map.count(LOGFILE_TAG) == 0) {
267         config_map[LOGFILE_TAG] = DEFAULT_LOG_FILE;
268     }
269     
270
271     vtl_debug_init(config_map[LOGFILE_TAG], enable_debug);
272
273
274     return 0;
275 }
276
277 void setup_disk(string disk_tag) {
278     printf("Setting up %s\n", disk_tag.c_str());
279 }
280
281
282
283 void usage() {
284   cout << "Usage: v3_nbd [config_file]" << endl;
285   return;
286 }