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 to the nbd server
[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 PORT_TAG  "port"
47 #define DISKS_TAG "disks"
48
49 // Turn on 64 bit file offset support (see 'man fseeko')
50 #define _FILE_OFFSET_BITS 64
51
52
53 using namespace std;
54 //using namespace __gnu_cxx;
55
56
57 typedef enum {INVALID, ISO, RAW} disk_type_t;
58
59 struct disk_info {
60     string filename;
61     string tag;
62     disk_type_t type;
63
64     FILE * disk_file;
65 };
66
67
68
69 struct eqsock {
70     bool operator()(const SOCK sock1, const SOCK sock2) const {
71         return sock1 == sock2;
72     }
73 };
74
75
76 // Server Port that we'll listen on
77 int server_port;
78
79 // List of disks being served 
80 // eqstr from vtl (config.h)
81 map<const string, struct disk_info *, eqstr> disks;
82
83
84 // List of open connections
85 map<SOCK, struct disk_info *, eqsock> conns;
86
87 // Enable Debugging
88 static const int enable_debug = 1;
89
90
91 void usage();
92 int config_nbd(string conf_file_name);
93 int serv_loop(int serv_sock);
94 void setup_disk(string disk_tag, config_t &config_map);
95
96
97 int __main (int argc, char ** argv);
98
99 disk_type_t get_disk_type(const string type_str) {
100
101     if (type_str == "ISO") {
102         return ISO;
103     } else if (type_str == "RAW") {
104         return RAW;
105     } 
106
107     return INVALID;
108 }
109
110
111 #ifdef linux
112
113 int main(int argc, char ** argv) {
114   return __main(argc, argv);
115 }
116
117 #elif WIN32
118
119 void main() {
120   __main(0, NULL);
121 }
122
123 #endif 
124
125 int __main (int argc, char ** argv) {
126   string config_file;
127   SOCK serv_sock;
128   if (argc > 2) {
129     usage();
130     exit(0);
131   }
132
133   if (argc == 2) {
134     config_file = string(argv[1]);
135   } else {
136     config_file = DEFAULT_CONF_FILE;
137   }
138
139  
140   if (config_nbd(config_file) == -1) {
141     cerr << "Configuration Error" << endl;
142     exit(-1);
143   }
144
145   // setup network sockets
146   serv_sock = CreateAndSetupTcpSocket();
147   
148   if (serv_sock == -1) {
149       cerr << "Could not create server socket, exiting..." << endl;
150       exit(-1);
151   }
152
153   if (BindSocket(serv_sock, server_port) == -1) {
154       cerr << "Could not bind socket to port: " << server_port << endl;
155       exit(-1);
156   }
157
158   if (ListenSocket(serv_sock) == -1) {
159       cerr << "Could not listen on server socket (port=" << server_port << ")" << endl;
160       exit(-1);
161   }
162
163
164   vtl_debug("Starting Server Loop\n");
165   serv_loop(serv_sock);
166
167   return 0;
168 }
169
170
171 #ifdef linux
172 int serv_loop(int serv_sock) {
173     fd_set all_set, read_set;
174     int max_fd = -1;
175     RawEthernetPacket pkt;
176
177     FD_ZERO(&all_set);
178     FD_SET(serv_sock, &all_set);
179     max_fd = serv_sock;
180
181
182     while (1) {
183         int nready = 0;
184         read_set = all_set;
185         nready = select(max_fd + 1, &read_set, NULL, NULL, NULL);
186     
187         if (nready == -1) {
188             if (errno == EINTR) {
189                 continue;
190             } else {
191                 vtl_debug("Select returned error\n");
192                 exit(-1);
193             }
194         }
195     
196
197         if (FD_ISSET(serv_sock, &read_set)) {
198             SOCK conn_socket;
199             struct sockaddr_in rem_addr;
200             socklen_t addr_len = sizeof(struct sockaddr_in);
201             // new connection
202             conn_socket = accept(serv_sock, (struct sockaddr *)&rem_addr, &addr_len);
203
204             if (conn_socket < 0) {
205                 if (errno == EINTR) {
206                     continue;
207                 } else {
208                     vtl_debug("Accept returned error\n");
209                     exit(-1);
210                 }
211             }
212
213             // configure socket
214
215         }
216     }
217
218     return 0;
219 }
220
221 #elif WIN32
222 int serv_loop(iface_t * iface, SOCK vnet_sock, struct vnet_config * vnet_info) {
223   int ret;
224   RawEthernetPacket pkt;
225   WSANETWORKEVENTS net_events;
226   WSAEVENT events[2];
227   DWORD event_i;
228   
229   events[VNET_EVENT] = WSACreateEvent();
230   
231   WSAEventSelect(vnet_sock, events[VNET_EVENT], FD_READ | FD_CLOSE);
232   events[IF_EVENT] = if_get_event(iface);
233   
234   while (1) {
235     event_i = WSAWaitForMultipleEvents(2, events, false, WSA_INFINITE, false);
236     cout << "Wait returned" << endl;
237     
238     if (event_i == WAIT_FAILED) {
239       cout << "ERROR: " <<   GetLastError() << endl;
240       exit(-1);
241     }
242     event_i -= WAIT_OBJECT_0;
243     
244     if (event_i == VNET_EVENT) {
245       
246       if (WSAEnumNetworkEvents(vnet_sock, events[event_i], &net_events) == SOCKET_ERROR) {
247         cout << "EnumEventsError: " << WSAGetLastError() << endl;
248         exit(-1);
249       }
250       if (net_events.lNetworkEvents & FD_READ) {
251         
252         // we received data
253         
254         if (vnet_info->link_type == TCP_LINK) {
255           pkt.Unserialize(vnet_sock);
256         } else if (vnet_info->link_type == UDP_LINK) {
257           pkt.UdpUnserialize(vnet_sock);
258         }
259         
260         process_outbound_pkt(&pkt);
261         
262         if_write_pkt(iface, &pkt);
263         
264       } else if (net_events.lNetworkEvents & FD_CLOSE) {
265         CLOSE(vnet_sock);
266         return 0;
267       }
268       
269     }
270   }
271   
272   return 0;
273 }
274 #endif
275
276
277
278 int config_nbd(string conf_file_name) {
279     config_t config_map;
280     
281     if (read_config(conf_file_name, &config_map) != 0) {
282         cerr << "Could not read config file..." << endl;
283         return -1;
284     }
285
286     if (config_map.count(PORT_TAG) > 0) {
287         server_port = atoi(config_map[PORT_TAG].c_str());
288     } else {
289         server_port = DEFAULT_PORT;
290     }
291         
292     if (config_map.count(DISKS_TAG) > 0) {
293         istringstream disk_stream(config_map[DISKS_TAG], istringstream::in);
294         string disk_tag;
295         int i = 0;
296         
297         while (disk_stream >> disk_tag) {
298
299             if (i >= MAX_DISKS) {
300                 cerr << "You specified too many disks, truncating..." << endl;
301                 break;
302             }
303             
304             setup_disk(disk_tag, config_map);
305             i++;
306         }       
307     } else {
308         cerr << "Must specify a set of disks" << endl;
309         return -1;
310     }
311     
312     if (config_map.count(LOGFILE_TAG) == 0) {
313         config_map[LOGFILE_TAG] = DEFAULT_LOG_FILE;
314     }
315     
316     vtl_debug_init(config_map[LOGFILE_TAG], enable_debug);
317
318     return 0;
319 }
320
321 void setup_disk(string disk_tag, config_t &config_map) {
322     string file_tag = disk_tag +  ".file";
323     string type_tag = disk_tag + ".type";
324     struct disk_info * disk = (struct disk_info *)malloc(sizeof(struct disk_info));
325
326     cout << "Setting up " << disk_tag.c_str() << endl;
327
328     if ((config_map.count(file_tag) == 0) && 
329         (config_map.count(type_tag) == 0)) {
330         cerr << "Missing Disk configuration directive for " << disk_tag << endl;
331     }
332
333     disk->tag = disk_tag;
334     disk->filename = config_map[file_tag];
335     disk->type = get_disk_type(config_map[type_tag]);
336
337     if (disk->type == RAW) {
338         disk->disk_file = fopen(disk->filename.c_str(), "w+");
339     } else if (disk->type == ISO) {
340         disk->disk_file = fopen(disk->filename.c_str(), "r");
341     }
342
343     disks[disk->tag] = disk;
344
345     return;
346 }
347
348
349
350
351
352
353 void usage() {
354   cout << "Usage: v3_nbd [config_file]" << endl;
355   return;
356 }