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 v3_nbd
[palacios.git] / misc / network_servers / v3_nbd / v3_nbd.cc
index 1f7ca53..a6efa9f 100644 (file)
@@ -17,7 +17,7 @@
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#include <string>
+
 #include <iostream>
 #include <fstream>
 #include <stdio.h>
 
 #endif
 
-#include "vtl.h"
+
+#include "v3_nbd.h"
+
+#define NBD_KEY "V3_NBD_1"
 
 
 #define DEFAULT_LOG_FILE "./status.log"
 #define MAX_DISKS 32
 
 #define LOGFILE_TAG "logfile"
-#define IP_ADDR_TAG "address"
 #define PORT_TAG  "port"
 #define DISKS_TAG "disks"
 
+// Turn on 64 bit file offset support (see 'man fseeko')
+#define _FILE_OFFSET_BITS 64
+
 
 using namespace std;
 //using namespace __gnu_cxx;
 
 
-typedef enum {ISO, RAW} disk_type_t;
-
-struct disk_info {
-    string filename;
-    string tag;
-    disk_type_t type;
+struct eqsock {
+    bool operator()(const SOCK sock1, const SOCK sock2) const {
+       return sock1 == sock2;
+    }
 };
 
-// eqstr from vtl (config.h)
-typedef map<const string, struct disk_info, eqstr> disk_list_t;
 
-struct nbd_config {
-    unsigned long server_addr;
-    int server_port;
-    disk_list_t disks;
-    int num_disks;
-};
+// Server Port that we'll listen on
+int server_port;
+
+// List of disks being served 
+// eqstr from vtl (config.h)
+map<const string, struct disk_info *, eqstr> disks;
 
+// List of open connections
+map<SOCK, struct disk_info *, eqsock> conns;
 
 
+// Enable Debugging
 static const int enable_debug = 1;
-static struct nbd_config g_nbd_conf;
+
 
 void usage();
 int config_nbd(string conf_file_name);
 int serv_loop(int serv_sock);
-void setup_disk(string disk_tag);
+void setup_disk(string disk_tag, config_t &config_map);
+
+int handle_new_connection(SOCK new_conn);
 
 
 int __main (int argc, char ** argv);
 
+
+
 #ifdef linux
 
 int main(int argc, char ** argv) {
@@ -99,7 +107,7 @@ void main() {
 
 int __main (int argc, char ** argv) {
   string config_file;
-  int serv_sock;
+  SOCK serv_sock;
   if (argc > 2) {
     usage();
     exit(0);
@@ -118,6 +126,23 @@ int __main (int argc, char ** argv) {
   }
 
   // setup network sockets
+  serv_sock = CreateAndSetupTcpSocket();
+  
+  if (serv_sock == -1) {
+      cerr << "Could not create server socket, exiting..." << endl;
+      exit(-1);
+  }
+
+  if (BindSocket(serv_sock, server_port) == -1) {
+      cerr << "Could not bind socket to port: " << server_port << endl;
+      exit(-1);
+  }
+
+  if (ListenSocket(serv_sock) == -1) {
+      cerr << "Could not listen on server socket (port=" << server_port << ")" << endl;
+      exit(-1);
+  }
+
 
   vtl_debug("Starting Server Loop\n");
   serv_loop(serv_sock);
@@ -128,39 +153,86 @@ int __main (int argc, char ** argv) {
 
 #ifdef linux
 int serv_loop(int serv_sock) {
-  fd_set all_set, read_set;
-  int max_fd = -1;
-  RawEthernetPacket pkt;
+    fd_set all_set, read_set;
+    int max_fd = -1;
+    RawEthernetPacket pkt;
 
-  FD_ZERO(&all_set);
-  FD_SET(serv_sock, &all_set);
-  max_fd = serv_sock;
 
+    list<SOCK> pending_cons;
 
-  while (1) {
-    int nready = 0;
-    read_set = all_set;
-    nready = select(max_fd + 1, &read_set, NULL, NULL, NULL);
-    
+    FD_ZERO(&all_set);
+    FD_SET(serv_sock, &all_set);
+    max_fd = serv_sock;
+
+
+    while (1) {
+       int nready = 0;
+       read_set = all_set;
+       write_set = all_set;
+       nready = select(max_fd + 1, &read_set, &write_set, NULL, NULL);
     
-    if (nready == -1) {
-      if (errno == EINTR) {
-       continue;
-      } else {
-       perror("Select returned error: ");
-       break;
-      }
-    }
+       if (nready == -1) {
+           if (errno == EINTR) {
+               continue;
+           } else {
+               vtl_debug("Select returned error\n");
+               exit(-1);
+           }
+       }
     
 
-    if (FD_ISSET(serv_sock, &read_set)) {
-      //vnet_recv();
+       if (FD_ISSET(serv_sock, &read_set)) {
+           SOCK conn_socket;
+           struct sockaddr_in rem_addr;
+           socklen_t addr_len = sizeof(struct sockaddr_in);
+           // new connection
+           conn_socket = accept(serv_sock, (struct sockaddr *)&rem_addr, &addr_len);
+
+           if (conn_socket < 0) {
+               if (errno == EINTR) {
+                   continue;
+               } else {
+                   vtl_debug("Accept returned error\n");
+                   exit(-1);
+               }
+           }
+
+           pending_cons.push_front(conn_socket);
+
+           FD_SET(conn_socket, &all_set);
+
+           if (conn_socket > max_fd) {
+               max_fd = conn_socket;
+           }
+
+           if (--nready <= 0) continue;
+       }
+
+       // handle open connections
+
+
+       // check pending connections
+
+       for (list<SOCK>::iterator pending_iter = pending_cons.begin();
+            pending_iter != pending_cons.end();
+            pending_iter++) {
+           
+           if (handle_new_connection(pending_iter.value()) == -1) {
+               // error
+           }
+           
+           pending_cons.remove(pending_iter);
+           
+           if (--nready <= 0) break;
+       }
+       
+       if (nready <= 0) continue;
+       
 
 
     }
-  }
 
-  return 0;
+    return 0;
 }
 
 #elif WIN32
@@ -194,7 +266,6 @@ int serv_loop(iface_t * iface, SOCK vnet_sock, struct vnet_config * vnet_info) {
       }
       if (net_events.lNetworkEvents & FD_READ) {
        
-       JRLDBG("Receied VNET Packet\n");
        // we received data
        
        if (vnet_info->link_type == TCP_LINK) {
@@ -221,6 +292,47 @@ int serv_loop(iface_t * iface, SOCK vnet_sock, struct vnet_config * vnet_info) {
 
 
 
+
+/* Negotiation:
+ * <NBD_KEY> <Disk Tag>\n
+ */
+
+int handle_new_connection(SOCK new_conn) {
+    string input;
+    string key_str;
+    string tag_str;
+    struct disk_info * disk = NULL;
+
+    GetLine(new_conn, input);
+
+    {
+       istringstream is(input, istringstream::in);
+       is >> key_str >> tag_str;
+    }
+
+    if (key_str != NBD_KEY) {
+       vtl_debug("Error: Invalid NBD key string (%s)\n", key_str.c_str());
+       return -1;
+    }
+
+    if (disks[tag_str].count() == 0) {
+       vtl_debug("Error: Requesting disk that does not exist (%s)\n", tag_str.c_str());
+       return -1;
+    }
+
+    // Check if already assigned...
+    disk = disks[tag_str];
+
+    if (!disk) {
+       return -1;
+    }
+
+    conns[new_conn] = disk;
+
+    return 0;
+}
+
+
 int config_nbd(string conf_file_name) {
     config_t config_map;
     
@@ -229,14 +341,10 @@ int config_nbd(string conf_file_name) {
        return -1;
     }
 
-    if (config_map.count(IP_ADDR_TAG) > 0) {
-       g_nbd_conf.server_addr = ToIPAddress(config_map[IP_ADDR_TAG].c_str());
-    } 
-
     if (config_map.count(PORT_TAG) > 0) {
-       g_nbd_conf.server_port = atoi(config_map[PORT_TAG].c_str());
+       server_port = atoi(config_map[PORT_TAG].c_str());
     } else {
-       g_nbd_conf.server_port = DEFAULT_PORT;
+       server_port = DEFAULT_PORT;
     }
        
     if (config_map.count(DISKS_TAG) > 0) {
@@ -251,35 +359,56 @@ int config_nbd(string conf_file_name) {
                break;
            }
            
-           setup_disk(disk_tag);
-
+           setup_disk(disk_tag, config_map);
            i++;
-       }
-       
-       g_nbd_conf.num_disks = i;
+       }       
     } else {
        cerr << "Must specify a set of disks" << endl;
        return -1;
     }
     
-    
     if (config_map.count(LOGFILE_TAG) == 0) {
        config_map[LOGFILE_TAG] = DEFAULT_LOG_FILE;
     }
     
-
     vtl_debug_init(config_map[LOGFILE_TAG], enable_debug);
 
-
     return 0;
 }
 
-void setup_disk(string disk_tag) {
-    printf("Setting up %s\n", disk_tag.c_str());
+void setup_disk(string disk_tag, config_t &config_map) {
+    string file_tag = disk_tag +  ".file";
+    string type_tag = disk_tag + ".type";
+
+    string type;
+
+
+    cout << "Setting up " << disk_tag.c_str() << endl;
+
+    if ((config_map.count(file_tag) == 0) && 
+       (config_map.count(type_tag) == 0)) {
+       cerr << "Missing Disk configuration directive for " << disk_tag << endl;
+    }
+
+    type = config_map[type_tag];  
+
+    if (type == "RAW") {
+       disks[disk->tag] = new raw_disk(config_map[file_tag]);;
+    } else if (type == "ISO") {
+       
+    }
+
+
+
+
+    return;
 }
 
 
 
+
+
+
 void usage() {
   cout << "Usage: v3_nbd [config_file]" << endl;
   return;