Krishna iResearch Intelligent Cloud Platform - VIRtual Generic Os - VIRGO - Linux kernel extensions for cloud
 All Classes
virgo_cloudexec_mempool.c
1 /***************************************************************************************
2 VIRGO - a linux module extension with CPU and Memory pooling with cloud capabilities
3 
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18 --------------------------------------------------------------------------------------------------
19 Copyright (C):
20 Srinivasan Kannan (alias) Ka.Shrinivaasan (alias) Shrinivas Kannan
21 Independent Open Source Developer, Researcher and Consultant
22 Ph: 9789346927, 9003082186, 9791165980
23 Open Source Products Profile(Krishna iResearch): http://sourceforge.net/users/ka_shrinivaasan
24 Personal website(research): https://sites.google.com/site/kuja27/
25 emails: ka.shrinivaasan@gmail.com, shrinivas.kannan@gmail.com, kashrinivaasan@live.com
26 --------------------------------------------------------------------------------------------------
27 
28 *****************************************************************************************/
29 
30 #include <linux/virgo_queue.h>
31 #include <linux/virgo_mempool.h>
32 #include <linux/virgocloudexecmempoolsvc.h>
33 #include <linux/virgo_config.h>
34 
35 #include <linux/string.h>
36 #include <linux/kallsyms.h>
37 
38 /*
39  VIRGO Memory Pooling Driver for virgo_malloc(), virgo_free(),virgo_set(),virgo_get()
40 */
41 
42 /*
43 #include <linux/kernel.h>
44 #include <linux/kthread.h>
45 #include <linux/sched.h>
46 #include <linux/module.h>
47 #include <linux/errno.h>
48 #include <linux/fcntl.h>
49 #include <linux/net.h>
50 #include <linux/in.h>
51 #include <linux/inet.h>
52 #include <linux/udp.h>
53 #include <linux/tcp.h>
54 #include <linux/string.h>
55 #include <linux/unistd.h>
56 #include <linux/slab.h>
57 #include <linux/netdevice.h>
58 #include <linux/skbuff.h>
59 #include <linux/file.h>
60 #include <linux/freezer.h>
61 #include <net/sock.h>
62 #include <net/checksum.h>
63 #include <net/ip.h>
64 #include <net/ipv6.h>
65 #include <net/tcp.h>
66 #include <net/tcp_states.h>
67 #include <asm/uaccess.h>
68 #include <asm/ioctls.h>
69 #include <trace/events/skb.h>
70 
71 #include <linux/module.h>
72 #include <linux/types.h>
73 #include <linux/uio.h>
74 #include <linux/unistd.h>
75 #include <linux/init.h>
76 
77 
78 #include <linux/sunrpc/types.h>
79 #include <linux/sunrpc/clnt.h>
80 #include <linux/sunrpc/xdr.h>
81 #include <linux/sunrpc/msg_prot.h>
82 #include <linux/sunrpc/svcsock.h>
83 #include <linux/sunrpc/stats.h>
84 #include <linux/sunrpc/xprt.h>
85 //#include "sunrpc.h"//
86 #include <linux/sunrpc/xprt.h>
87 //#include "netns.h"//
88 
89 #define BUF_SIZE 500
90 typedef int (*FPTR)(void *args);
91 
92 static int virgocloudexec_mempool_create(void);
93 static int virgocloudexec_mempool_recvfrom(void);
94 static int virgocloudexec_mempool_sendto(void);
95 
96 static struct svc_xprt_ops virgo_ops = {
97  .xpo_create = virgocloudexec_mempool_create,
98  .xpo_recvfrom = virgocloudexec_mempool_recvfrom,
99  .xpo_sendto = virgocloudexec_mempool_sendto
100 };
101 
102 static struct svc_xprt_class virgo_class = {
103  .xcl_name = "virgo",
104  .xcl_owner = THIS_MODULE,
105  .xcl_ops = &virgo_ops
106 };
107 
108 
109 
110 struct task_struct *task;
111 int (*mempoolFunction_ptr)(void*);
112 char* mempoolFunction;
113 int error;
114 char buffer[BUF_SIZE];
115 struct socket *sock;
116 struct sockaddr_in sin;
117 int len=0;
118 struct socket *clientsock;
119 struct kvec iov;
120 struct msghdr msg;
121 int buflen=BUF_SIZE;
122 int nr=0;
123 int args=0;
124 
125 char** node_ip_addrs_in_cloud;
126 int num_cloud_nodes;
127 */
128 
129 
130 /*
131 * The wrapper function that based on switch parameterIsExecutable (values 0,1,2) executes the binary or function data from virgo_malloc
132 * system call in either kernel or user address-spaces
133 * - Ka.Shrinivaasan
134 */
135 
136 int mempool_func(void* args)
137 {
138  /*
139  * Lack of reflection kind of facilities requires map of function_names to pointers_to_functions to be executed
140  * on cloud. Function name has to be lookedup in the map to get pointer to function. This map is not scalable
141  * if number of functions are in millions and size of the map increases linearly. Also having it in memory is
142  * both CPU and memory intensive.
143  *
144  * Moreover this map has to be synchronized in all nodes for coherency and consistency which is another intensive task.
145  * Thus name to pointer function table is at present not implemented. Suitable way to call a function by name of the function
146  * is yet to be found out and references in this topic are scarce.
147  * - Ka.Shrinivaasan
148  */
149 
150  /*
151  *If parameterIsExecutable is set to 2, the data from virgo_malloc() is a function and is executed within kernel address-space itself
152  *This invokes kmalloc() to allocate kernel memory. Intermodule function invocation functionality which enables complete takeover
153  *of lowlevel system cards, PCI, RAM etc., has been implemented and testcase kern.logs are under ./test_logs/
154  *
155  *If parameterIsExecutable is set to 1 the data received from virgo_malloc() is not a function but name of executable
156  *This executable is then run on usermode using call_usermodehelper() which internally takes care of queueing the workstruct
157  *and executes the binary as child of keventd and reaps silently. Thus workqueue component of kernel is indirectly made use of.
158  *This is sometimes more flexible alternative that executes a binary itself on cloud and
159  *is preferable to clone()ing a function on cloud. Virgo_clone() syscall client or telnet needs to send the message with name of binary.
160  *
161  *If parameterIsExecutable is set to 0 then data received from virgo_malloc() is name of a function and is executed in else clause
162  *using dlsym() lookup and pthread_create() in user space. This unifies both call_usermodehelper() and creating a userspace thread
163  *with a fixed binary which is same for any function. The dlsym lookup requires mangled function names which need to be sent by
164  *virgo_malloc or telnet. This is far more efficient than a function pointer table.
165  *call_usermodehelper() Kernel upcall to usermode to exec a fixed binary that would inturn execute the mempoolFunction in userspace
166  *by spawning a pthread. mempoolFunction is name of the function and not binary. This clone function will be dlsym()ed
167  *and a pthread will be created by the fixed binary. Name of the fixed binary is hardcoded herein as
168  *"virgo_kernelupcall_plugin". This fixed binary takes malloc function as argument. For testing libvirgo_mempool.so has been created from
169  *virgo_cloud_test.c and separate build script to build the cloud function binaries has been added.
170  *
171  *- Ka.Shrinivaasan
172  */
173 
174  char buffer[BUF_SIZE];
175  int ret=0;
176  char *argv[8];
177  char *envp[3];
178  char* mempoolFunction = (char*)args;
179  struct virgo_mempool_args* vmargs=parse_virgomempool_command(kstrdup(mempoolFunction,GFP_KERNEL));
180  void* virgo_mempool_ret;
181 
182  if (parameterIsExecutable==2)
183  {
184  if(use_as_kingcobra_service==1)
185  {
186  printk("mempool_func(): VIRGO cloudexec mempool is used as KingCobra service, invoking push_request() in kernelspace for data: %s\n",mempoolFunction);
187  struct virgo_request *vrq=kmalloc(sizeof(struct virgo_request),GFP_ATOMIC);
188  vrq->data=kstrdup(mempoolFunction,GFP_ATOMIC);
189  vrq->next=NULL;
190  push_request(vrq);
191  /*
192  task=kthread_create(push_request, (void*)args, "KingCobra push_request() thread");
193  woken_up_2=wake_up_process(task);
194  */
195  }
196  else
197  {
198  struct task_struct *task;
199  int woken_up_2=0;
200  printk(KERN_INFO "mempool_func(): creating kernel thread and waking up, parameterIsExecutable=%d\n", parameterIsExecutable);
201  printk(KERN_INFO "Creating Kernel Thread for %s in virgo_cloud_mempool_kernelspace mempool driver module with mempool_args[0]=%s, mempool_args[1]=%s\n",vmargs->mempool_cmd,vmargs->mempool_args[0],vmargs->mempool_args[1]);
202 
203  /*
204  Temporarily commenting kthread creation for the kernelspace virgo mempool
205  ops execution as return value from a kthread function is needed which is
206  difficult and circuitous to do with kthread. Instead the functions in the
207  kernel module virgo_cloud_mempool_kernelspace.ko are directly invoked using
208  intermodule kernelspace invocation.
209  */
210  /*task=kthread_create(toFuncPtr(kstrdup(strcat(vmargs->mempool_cmd,"_kernelspace"),GFP_KERNEL)), (void*)vmargs, "mempoolFunction kernelspace thread");*/
211  virgo_mempool_ret=toFuncPtr(kstrdup(strcat(kstrdup(vmargs->mempool_cmd,GFP_KERNEL),"_kernelspace"),GFP_KERNEL))(vmargs);
212 
213  printk(KERN_INFO "mempool_func(): virgo mempool kernelspace module returns value virgo_mempool_ret=%p\n", (char*)virgo_mempool_ret);
214  /*
215  woken_up_2=wake_up_process(task);
216  */
217  }
218  }
219  else if(parameterIsExecutable==1)
220  {
221  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_cloudexec_mempool_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
222  fd_install(1,file_stdout);
223  fd_install(2,file_stdout);
224  argv[0]=kstrdup(mempoolFunction,GFP_KERNEL);
225  /*
226  argv[2]=kstrdup(strcat(argv[2], " >> /home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_kernelupcall_plugin_userspace_exec.log"),GFP_KERNEL);
227  */
228  argv[1]=NULL;
229  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/";
230  envp[1]="HOME=/home/kashrinivaasan";
231  envp[2]=NULL;
232  /* call_usermodehelper() Kernel upcall to usermode */
233  /* mempoolFunction contains name of the binary and not the name of the function */
234  printk("mempool_func(): executing call_usermodehelper for data from virgo_malloc: %s - parameterIsExecutable=%d\n",mempoolFunction, parameterIsExecutable);
235  ret=call_usermodehelper(mempoolFunction, argv, envp, UMH_WAIT_EXEC);
236  /*ret=call_usermodehelper("/bin/bash", argv, envp, UMH_WAIT_PROC);*/
237  printk("mempool_func(): call_usermodehelper() for binary %s returns ret=%d\n", mempoolFunction, ret);
238  filp_close(file_stdout,NULL);
239  }
240  else if (parameterIsExecutable==0)
241  {
242  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_cloudexec_mempool_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
243  fd_install(1,file_stdout);
244  fd_install(2,file_stdout);
245  argv[0]=kstrdup("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_kernelupcall_plugin",GFP_KERNEL);
246  argv[1]=kstrdup(mempoolFunction,GFP_KERNEL);
247  argv[2]=NULL;
248  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games::/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/";
249  envp[1]="HOME=/home/kashrinivaasan";
250  envp[2]=NULL;
251  printk(KERN_INFO "mempool_func(): executing the virgo_malloc() syscall function parameter in cloud - parameterIsExecutable=%d, mempoolFunction=%s\n",parameterIsExecutable,mempoolFunction);
252  ret=call_usermodehelper("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_kernelupcall_plugin",argv,envp,UMH_WAIT_EXEC);
253 
254  /*
255  argv[0]=kstrdup("/bin/bash",GFP_KERNEL);
256  argv[1]=kstrdup("-c",GFP_KERNEL);
257  argv[2]=kstrdup("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_kernelupcall_plugin",GFP_KERNEL);
258  argv[3]=kstrdup(mempoolFunction,GFP_KERNEL);
259  argv[4]=NULL;
260  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games";
261  envp[1]="HOME=/home/kashrinivaasan";
262  envp[2]=NULL;
263  printk(KERN_INFO "mempool_func(): executing the virgo_malloc() syscall function parameter in cloud - parameterIsExecutable=%d\n",parameterIsExecutable);
264  ret=call_usermodehelper("/bin/bash",argv,envp,UMH_WAIT_PROC);
265  */
266  printk("mempool_func(): call_usermodehelper() for virgo_kernelupcall_plugin returns ret=%d\n", ret);
267  /*
268  Depending on scheduling priority either this or other message in virgocloudexec_mempool_sendto() will be sent to
269  virgo_malloc() remote syscall
270  */
271  strcpy(buffer,"mempool_func(): cloudclonethread executed for mempool_func(), sending message to virgo_malloc() remote syscall client");
272  filp_close(file_stdout,NULL);
273  }
274  /*return 1;*/
275  return virgo_mempool_ret;
276 }
277 
278 char* strip_control_M(char* str)
279 {
280  printk("strip_control_M(): str=%s before strsep\n",str);
281  char* dupstr=kstrdup(str, GFP_KERNEL);
282  char* newstr=strsep(&dupstr, "\r\n ");
283  printk("strip_control_M(): newstr=%s after carriage return newline strsep\n",newstr);
284  return newstr;
285 }
286 
287 int kernel_space_func(void* args)
288 {
289  printk(KERN_INFO "kernel_space_func(): parameterIsExecutable=2; executing function in kernel address space\n");
290  return 0;
291 }
292 
293 void read_virgo_config()
294 {
295  /* virgo_cloud.conf contains a string of comma separated list of IP addresses in the virgo cloud .Read and strsep() it. */
296 
297  loff_t bytesread=0;
298  loff_t pos=0;
299  mm_segment_t fs;
300 
301  /*
302  * It is redundant to use kallsyms_lookup for exported symbols for virgo cloud initialization.
303  * kallsyms_lookup is for non-exported symbols.
304  *
305  * - Ka.Shrinivaasan 10 July 2013
306  *
307 
308  node_ip_addrs_in_cloud=(char**)kallsyms_lookup_name("node_ip_addrs_in_cloud");
309  num_cloud_nodes=kallsyms_lookup_name("num_cloud_nodes");
310 
311  printk(KERN_INFO "virgo kernel service: read_virgo_config(): virgo_cloud config being read... \n");
312  printk(KERN_INFO "virgo kernel service: read_virgo_config(): num_cloud_nodes=%d #### node_ip_addrs_in_cloud=%s\n", num_cloud_nodes,node_ip_addrs_in_cloud);
313  */
314 
315  fs=get_fs();
316  set_fs(get_ds());
317  struct file* f=NULL;
318  f=filp_open("/etc/virgo_cloud.conf", O_RDONLY, 0);
319 
320  char buf[256];
321  int i=0;
322 
323  int k=0;
324  for(k=0;k<256;k++)
325  buf[k]=0;
326 
327  for(k=0; k < num_cloud_nodes; k++)
328  printk(KERN_INFO "virgo kernel service: read_virgo_config(): before reading virgo_cloud.conf - virgo_cloud ip address - %d: %s\n", k+1, node_ip_addrs_in_cloud[k]);
329 
330  printk(KERN_INFO "read_virgo_config(): virgo_cloud config file being read \n");
331 
332 
333  if(f !=NULL)
334  {
335  /*f->f_op->read(f, buf, sizeof(buf), &f->f_pos);*/
336  bytesread=vfs_read(f, buf, 256, &pos);
337  /*strcpy(node_ip_addrs_in_cloud[i],buf);*/
338  printk(KERN_INFO "do_virgo_cloud_init(): virgo_cloud config file string of comma separated IPs : %s \n",buf);
339  /*printk(KERN_INFO "do_virgo_cloud_init(): virgo_cloud config file line %d \n",i);*/
340  pos=pos+bytesread;
341  }
342  /*num_cloud_nodes=tokenize_list_of_ip_addrs(buf);*/
343  char* delim=",";
344  char* token=NULL;
345  char* bufdup=kstrdup(buf,GFP_KERNEL);
346  printk(KERN_INFO "tokenize_list_of_ip_addrs(): bufdup = %s\n",bufdup);
347  while(bufdup != NULL)
348  {
349  token=strsep(&bufdup, delim);
350  printk(KERN_INFO "tokenize_list_of_ip_addrs(): %s\n",token);
351  node_ip_addrs_in_cloud[i]=kstrdup(token,GFP_KERNEL);
352  printk(KERN_INFO "tokenize_list_of_ip_addrs(): node_ip_addrs_in_cloud[%d] = %s\n",i,node_ip_addrs_in_cloud[i]);
353  i++;
354  }
355  num_cloud_nodes=i;
356  set_fs(fs);
357  filp_close(f,NULL);
358 }
359 
360 /*
361 Above tokenization made into a function - if needed can be used as multipurpose exported function
362 */
363 int tokenize_list_of_ip_addrs(char* buf)
364 {
365  char* delim=",";
366  char* token=NULL;
367  char* bufdup=kstrdup(buf,GFP_KERNEL);
368  printk(KERN_INFO, "tokenize_list_of_ip_addrs(): bufdup = %s\n",bufdup);
369  int i=0;
370  while(bufdup != NULL)
371  {
372  token=strsep(&bufdup, delim);
373  printk(KERN_INFO, "tokenize_list_of_ip_addrs(): %s\n",token);
374  /*strcpy(node_ip_addrs_in_cloud[i], token);*/
375  i++;
376  }
377  return i;
378 }
379 
380 /*
381 FPTR get_function_ptr_from_str(char* mempoolFunction)
382 {
383  return mempool_func;
384 }
385 */
386 
387 static int __init
388 virgocloudexec_mempool_init(void)
389 {
390  int error;
391  static struct sockaddr_in sin;
392 
393  printk(KERN_INFO "virgocloudexec_mempool_init(): doing init() of virgocloudexec_mempool kernel module\n");
394  printk(KERN_INFO "virgocloudexec_mempool_init(): starting virgo cloudexec service kernel thread\n");
395 
396  printk(KERN_INFO "virgocloudexec_mempool_init(): invoking read_virgo_config()\n");
397  read_virgo_config();
398 
399  memset(&sin, 0, sizeof(struct sockaddr_in));
400  sin.sin_family=AF_INET;
401  sin.sin_addr.s_addr=htonl(INADDR_ANY);
402  sin.sin_port=htons(30000);
403 
404  /*stack=kmalloc(65536, GFP_KERNEL);*/
405  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
406  printk(KERN_INFO "virgocloudexec_mempool_init(): sock_create() returns error code: %d\n",error);
407 
408  error = kernel_bind(sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in));
409  printk(KERN_INFO "virgocloudexec_mempool_init(): kernel_bind() returns error code: %d\n",error);
410 
411  error = kernel_listen(sock, 2);
412  printk(KERN_INFO "virgocloudexec_mempool_init(): kernel_listen() returns error code: %d\n", error);
413 
414  virgo_cloudexec_mempool_service(NULL);
415 
416  /*
417  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/mempooling/virgocloudexec_mempool/virgo_cloudexec_mempool_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
418  fd_install(1,file_stdout);
419  fd_install(2,file_stdout);
420  */
421  return 0;
422 }
423 EXPORT_SYMBOL(virgocloudexec_mempool_init);
424 
425 int virgocloudexec_mempool_create(void)
426 {
427  int error;
428 
429  /*
430  Blocking mode works in this commit again. No changes were made in virgo_malloc() or driver code.
431  Hence making it a blocking socket. Root cause for this weird behaviour remains unknown.
432  -Ka.Shrinivaasan
433  */
434 
435  /*
436  Multithreaded VIRGO Kernel Service
437  ----------------------------------
438  */
439  struct socket *clientsock;
440 
441  clientsock=NULL;
442  error = kernel_accept(sock, &clientsock, 0);
443 
444  /*
445  Blocking mode was working and kernel thread was listening and accepting connections without blocking the bootup till previous commit,
446  but suddenly it started to block on startup. Reason unknown (could be anything from hardware microcode update to external
447  causes viz., intrusion. These kind of events recur with high frequency. Needs further investigation).
448  There seems to be no error in the driver kernel service thread or syscall client.
449 
450  Making it temporarily O_NONBLOCK which seems to be quite a cleaner way despite EAGAIN to accept connections as this is always
451  in a while loop for server.
452 
453  Moreover the driver modules_install places it in /lib/modules/`uname -r`/extra which did not occur in previous commit. Origin
454  again mysterious.
455 
456  -Ka.Shrinivaasan
457  error = kernel_accept(sock, &clientsock, O_NONBLOCK);
458  */
459  /*
460  if(error==-EAGAIN)
461  printk(KERN_INFO "kernel_accept() returns -EAGAIN\n");
462  printk(KERN_INFO "virgocloudexec_mempool_create(): kernel_accept() returns error code: %d\n",error);
463  printk(KERN_INFO "virgocloudexec_mempool_create(): kernel_accept() clientsock: %u\n",clientsock);
464  */
465  return clientsock;
466 }
467 EXPORT_SYMBOL(virgocloudexec_mempool_create);
468 
469 void* virgocloudexec_mempool_recvfrom(struct socket* clsock)
470 {
471  char* mempoolFunction;
472  struct sockaddr_in sin;
473  void* virgo_mempool_func_ret;
474 
475  /*
476  Multithreaded VIRGO Kernel Service
477  ----------------------------------
478  */
479  struct socket *clientsock=clsock;
480  struct kvec iov;
481  struct msghdr msg = { NULL, };
482  int buflen=BUF_SIZE;
483  void *args=NULL;
484  int nr=1;
485 
486  struct task_struct *task;
487  int error;
488  char buffer[BUF_SIZE];
489  int len=0;
490 
491  char* client_ip_str;
492 
493  /*
494  do kernel_recvmsg() to get the function data to be executed on a thread
495  */
496  /*
497  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): clientsock: %u\n",clientsock);
498  */
499  if(clientsock != NULL )
500  {
501  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): before kernel_recvmsg()\n");
502  memset(buffer, 0, BUF_SIZE);
503  iov.iov_base=(void*)buffer;
504  //iov.iov_len=sizeof(buffer);
505  iov.iov_len=BUF_SIZE;
506  msg.msg_name = (struct sockaddr *) &sin;
507  msg.msg_namelen = sizeof(struct sockaddr);
508  msg.msg_iov = (struct iovec *) &iov;
509  msg.msg_iovlen = 1;
510  msg.msg_control = NULL;
511  msg.msg_controllen = 0;
512  /*msg.msg_flags=0;*/
513  msg.msg_flags=MSG_NOSIGNAL;
514 
515  /*
516  len = kernel_recvmsg(clientsock, &msg, &iov, nr, BUF_SIZE, msg.msg_flags);
517  */
518  len = kernel_recvmsg(clientsock, &msg, &iov, 1, buflen, msg.msg_flags);
519  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): kernel_recvmsg() returns len: %d\n",len);
520  /*
521  parse the message and invoke kthread_create()
522  do kernel_sendmsg() with the results
523  */
524  mempoolFunction = strip_control_M(kstrdup(buffer,GFP_KERNEL));
525  /*mempoolFunction[strlen(mempoolFunction)-2]='\0';*/
526  if(use_as_kingcobra_service==1)
527  {
528  client_ip_str=kmalloc(BUF_SIZE,GFP_ATOMIC);
529  struct sockaddr_in* ipaddr=(struct sockaddr_in*)clientsock;
530  long ipaddr_int = ntohl(ipaddr->sin_addr.s_addr);
531  /*inet_ntop(AF_INET, &ipaddr_int, client_ip_str, BUF_SIZE);*/
532  sprintf(client_ip_str,"%x",ipaddr_int);
533  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): client_ip_str = %s\n",client_ip_str);
534  client_ip_str=kstrdup(strcat(client_ip_str,"#"),GFP_ATOMIC);
535  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): client_ip_str with # appended = %s\n",client_ip_str);
536  char* request_header=kmalloc(BUF_SIZE,GFP_ATOMIC);
537  sprintf(request_header,"REQUEST#");
538  request_header=kstrdup(strcat(request_header,client_ip_str),GFP_ATOMIC);
539  char* logicaltimestamp=generate_logical_timestamp();
540  request_header=kstrdup(strcat(request_header,logicaltimestamp),GFP_ATOMIC);
541  mempoolFunction = kstrdup(strcat(request_header,mempoolFunction),GFP_ATOMIC);
542  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): use_as_kingcobra_service=1, mempoolFunction with prepended request header and client ip=%s\n",mempoolFunction);
543  }
544 
545 
546  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): kernel_recvmsg() returns in recv: iov.iov_base=%s, buffer: %s\n", iov.iov_base, buffer);
547  print_buffer(buffer);
548  le32_to_cpus(buffer);
549  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): kernel_recvmsg() le32 to cpu %s\n", buffer);
550  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): mempoolFunction : %s \n", mempoolFunction);
551  /*mempoolFunction_ptr = get_function_ptr_from_str(mempoolFunction);*/
552  /*task=kthread_run(mempoolFunction_ptr, (void*)args, "cloudclonethread");*/
553  args=(void*)mempoolFunction;
554 
555  /*
556  Temporarily commenting kthread creation for the kernelspace virgo mempool ops
557  execution as return value from a kthread function is needed which is difficult
558  and circuitous to do with kthread. Instead the mempool_func is directly invoked.
559  */
560  /*task=kthread_create(mempool_func, (void*)args, "mempool_func thread");*/
561  virgo_mempool_func_ret=mempool_func((void*)args);
562 
563  /*
564  int woken_up=wake_up_process(task);
565  printk(KERN_INFO "virgocloudexec_mempool_recvfrom(): clone thread woken_up : %d\n",woken_up);
566  */
567 
568  /*
569  task=kthread_create(mempool_func, (void*)args, "cloudclonethread");
570  strcpy(buffer,"cloudclonethread executed");
571  */
572  }
573  return virgo_mempool_func_ret;
574 }
575 EXPORT_SYMBOL(virgocloudexec_mempool_recvfrom);
576 
577 void print_buffer(char* buffer)
578 {
579  printk(KERN_INFO "virgo_cloudexec_mempool: print_buffer(): ");
580  int i=0;
581  for(i=0; i < BUF_SIZE; i++)
582  printk(KERN_INFO "%c", buffer[i]);
583  printk(KERN_INFO "\n");
584 }
585 
586 int virgocloudexec_mempool_sendto(struct socket* clsock, void* virgo_mempool_ret)
587 {
588 
589  /*
590  Multithreaded VIRGO Kernel Service
591  ----------------------------------
592  */
593 
594  struct sockaddr_in sin;
595  struct socket *clientsock=clsock;
596  struct kvec iov;
597  struct msghdr msg = { NULL, };
598  int buflen=BUF_SIZE;
599  void *args=NULL;
600  int nr=1;
601 
602  struct task_struct *task;
603  int error;
604  char buffer[BUF_SIZE];
605  int len=0;
606 
607  /*
608  printk(KERN_INFO "virgocloudexec_mempool_sendto(): clientsock: %u\n",clientsock);
609  */
610  if(clientsock != NULL)
611  {
612  /*strcpy(buffer,"virgo_cloudexec_mempool_sendto(): cloudclonethread executed for mempool_func(), sending message to virgo_malloc() remote syscall client\n");*/
613  /*iov.iov_base=(void*)buffer;*/
614  /*memset(buffer, 0, sizeof(buffer));*/
615 
616  printk(KERN_INFO "virgocloudexec_mempool_sendto(): virgo_mempool_ret=%s\n",virgo_mempool_ret);
617  if(strncmp(virgo_mempool_ret,"virgodata:",10)==0)
618  {
619  /* data retrieved by virgo_get */
620  printk(KERN_INFO "virgocloudexec_mempool_sendto(): data sent=%s\n",virgo_mempool_ret+10);
621  strcpy(buffer,kstrdup(virgo_mempool_ret+10,GFP_KERNEL));
622  }
623  else
624  {
625  /* address alloc-ed by virgo_malloc, or return value of virgo_set or virgo_free */
626  printk(KERN_INFO "virgocloudexec_mempool_sendto(): address sent=%p\n",virgo_mempool_ret);
627  strcpy(buffer,toAddressString(virgo_mempool_ret));
628  }
629  iov.iov_base=buffer;
630  iov.iov_len=BUF_SIZE;
631  /*iov.iov_len=sizeof(buffer);*/
632  msg.msg_name = (struct sockaddr *) &sin;
633  msg.msg_namelen = sizeof(struct sockaddr);
634  msg.msg_iov = (struct iovec *) &iov;
635  msg.msg_iovlen = 1;
636  msg.msg_control = NULL;
637  msg.msg_controllen = 0;
638  msg.msg_flags=0;
639 
640  int ret;
641  printk(KERN_INFO "virgocloudexec_mempool_sendto(): before kernel_sendmsg() for send buffer: %s\n", buffer);
642  ret = kernel_sendmsg(clientsock, &msg, &iov, 1, buflen);
643  /*len = kernel_recvmsg(clientsock, &msg, &iov, 1, buflen, msg.msg_flags);*/
644  /*ret = kernel_sendmsg(clientsock, &msg, &iov, nr, buflen);*/
645  printk(KERN_INFO "virgocloudexec_mempool_sendto(): kernel_sendmsg() returns ret: %d\n",ret);
646  /*
647  printk(KERN_INFO "virgocloudexec_mempool_sendto(): kernel_recvmsg() returns len: %d\n",len);
648  printk(KERN_INFO "virgocloudexec_mempool_sendto(): kernel_recvmsg() returns in recv buffer: %s\n", buffer);
649  */
650 
651  /*
652  kernel_sock_shutdown(clientsock,SOCK_WAKE_URG);
653  printk(KERN_INFO "virgocloudexec_mempool_sendto(): Shut down Kernel Side Client Socket with SOCK_WAKE_URG after sendmsg \n");
654  */
655  sock_release(clientsock);
656  printk(KERN_INFO "virgocloudexec_mempool_sendto(): sock_release invoked on client socket \n");
657  }
658  return 0;
659 
660  /*
661  struct task_struct *task;
662  int error;
663  struct addrinfo hints;
664  struct socket* sock;
665  struct socket* client_sock;
666  struct addrinfo *result, *rp;
667  int sfd, s;
668  struct sockaddr_storage peer_addr;
669  socklen_t peer_addr_len;
670  ssize_t nread;
671  char buf[BUF_SIZE];
672  struct kvec iov;
673  struct msghdr msg = {
674  .msg_flags = MSG_DONTWAIT,
675  };
676 
677  memset(&hints, 0, sizeof(struct addrinfo));
678  hints.ai_family = AF_UNSPEC; / Allow IPv4 or IPv6 /
679  hints.ai_socktype = SOCK_STREAM; / Datagram socket /
680  hints.ai_flags = AI_PASSIVE; / For wildcard IP address /
681  hints.ai_protocol = 0; / Any protocol /
682  hints.ai_canonname = NULL;
683  hints.ai_addr = NULL;
684  hints.ai_next = NULL;
685 
686  char* cloud_clone_port=60000;
687 
688  stack=kmalloc(65536, GFP_KERNEL);
689  iov.iov_base=(void*)buf;
690  iov.iov_len=BUF_SIZE;
691  s = getaddrinfo(NULL, cloud_clone_port, &hints, &result);
692 
693  sock_create(rp->ai_family, rp->ai_socktype,
694  rp->ai_protocol, sock);
695 
696  kernel_bind(sock, rp->ai_addr, rp->ai_addrlen);
697  kernel_listen(sock,64);
698 
699  freeaddrinfo(result); / No longer needed /
700 
701  error = kernel_accept(sock, clientsock, O_NONBLOCK);
702 
703  for (;;) {
704  nread = kernel_recvmsg(clientsock, &msg, buflen, &iov, nr, msg.msg_flags);
705 
706  char* mempoolFunction = kstrdup(iov.iov_base,GFP_KERNEL);
707 
708  int ((*mempoolFunction_ptr)(void*));
709  mempoolFunction_ptr = get_function_ptr_from_str(mempoolFunction);
710  int *args=0;
711  task=kthread_create(mempoolFunction_ptr, (void*)args, "cloudclonethread");
712  strcpy(buffer,"cloudclonethread executed");
713  iov.iov_base=(void*)buf;
714  iov.iov_len=BUF_SIZE;
715  kernel_sendmsg(clientsock, &msg, buflen, &iov, nr);
716  }
717  */
718 
719 }
720 EXPORT_SYMBOL(virgocloudexec_mempool_sendto);
721 
722 
723 static void __exit
724 virgocloudexec_mempool_exit(void)
725 {
726  printk(KERN_INFO "exiting virgocloudexec_mempool kernel module \n");
727  /*filp_close(file_stdout,NULL);*/
728  do_exit(1);
729 }
730 EXPORT_SYMBOL(virgocloudexec_mempool_exit);
731 
732 /*
733 Arguments Parser for VIRGO memory pooling commands-virgo_cloud_malloc,virgo_cloud_free
734 virgo_cloud_set,virgo_cloud_get- sent from virgo_malloc syscall
735 */
736 
737 struct virgo_mempool_args* parse_virgomempool_command(char* mempoolFunction)
738 {
739  struct virgo_mempool_args* vmargs=kmalloc(sizeof(struct virgo_mempool_args),GFP_KERNEL);
740  vmargs->mempool_cmd=kstrdup(strsep(&mempoolFunction, "("),GFP_KERNEL);
741  printk(KERN_INFO "parse_virgomempool_command: vmargs->mempool_cmd: %s\n", vmargs->mempool_cmd);
742 
743  if(strcmp(vmargs->mempool_cmd,"virgo_cloud_malloc")==0 || strcmp(vmargs->mempool_cmd,"virgo_cloud_free")==0 || strcmp(vmargs->mempool_cmd,"virgo_cloud_get")==0)
744  {
745  vmargs->mempool_args[0]=kstrdup(strsep(&mempoolFunction,")"),GFP_KERNEL);
746  printk(KERN_INFO "parse_virgomempool_command: vmargs->mempool_args[0]: %s\n", vmargs->mempool_args[0]);
747 
748  vmargs->mempool_args[1]=NULL;
749  }
750  else
751  {
752 
753  vmargs->mempool_args[0]=kstrdup(strsep(&mempoolFunction,","),GFP_KERNEL);
754  vmargs->mempool_args[1]=kstrdup(strsep(&mempoolFunction,")"),GFP_KERNEL);
755  printk(KERN_INFO "parse_virgomempool_command: vmargs->mempool_args[0]: %s\n", vmargs->mempool_args[0]);
756  printk(KERN_INFO "parse_virgomempool_command: vmargs->mempool_args[1]: %s\n", vmargs->mempool_args[1]);
757  vmargs->mempool_args[2]=NULL;
758  }
759  return vmargs;
760 }
761 
762 FPTR toFuncPtr(char* functionName)
763 {
764  if(strcmp(functionName, "virgo_cloud_malloc_kernelspace")==0)
765  return virgo_cloud_malloc_kernelspace;
766  if(strcmp(functionName, "virgo_cloud_free_kernelspace")==0)
767  return virgo_cloud_free_kernelspace;
768  if(strcmp(functionName, "virgo_cloud_set_kernelspace")==0)
769  return virgo_cloud_set_kernelspace;
770  if(strcmp(functionName, "virgo_cloud_get_kernelspace")==0)
771  return virgo_cloud_get_kernelspace;
772 }
773 
774 char* toAddressString(char* ptr)
775 {
776  char* strAddress=kmalloc(BUF_SIZE, GFP_KERNEL);
777  sprintf(strAddress,"%p",ptr);
778  printk(KERN_INFO "toAddressString(): address=%p, sprintf strAddress=[%s]\n", ptr, strAddress);
779  return strAddress;
780 }
781 
782 char* generate_logical_timestamp(void)
783 {
784  char* logicaltimestamp=NULL;
785  if(EventNet_timestamp==1)
786  {
787  return "notimplemented#";
788  }
789  else if(machine_timestamp==1)
790  {
791  logicaltimestamp=kmalloc(BUF_SIZE, GFP_KERNEL);
792  /* generates a hash terminated timestamp string*/
793  sprintf(logicaltimestamp,"%ld:%ld#",CURRENT_TIME,CURRENT_TIME_SEC);
794  printk(KERN_INFO "generate_logical_timestamp(): machine_timestamp=1, generating timestamp for this request as %s",logicaltimestamp);
795  return logicaltimestamp;
796 
797  }
798  else if(other_timestamp_cloudservice==1)
799  {
800  return "notimplemented#";
801  }
802 }
803 
804 MODULE_LICENSE("GPL");
805 module_init(virgocloudexec_mempool_init);
806 module_exit(virgocloudexec_mempool_exit);