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.


Release 1.0
[palacios.git] / geekos / src / geekos / socket.c
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, Lei Xia <xiaxlei@gmail.com>
12  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Jack Lange <jarusl@cs.northwestern.edu>
16  * Author: Lei Xia <xiaxlei@gmail.com>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22 #include <geekos/socket.h>
23 #include <geekos/malloc.h>
24 #include <geekos/ne2k.h>
25
26 #ifdef UIP
27
28 #include <uip/uip.h>
29 #include <uip/uip_arp.h>
30
31 #include <geekos/vmm_stubs.h>
32 #include <geekos/debug.h>
33 #include <geekos/timer.h>
34
35 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
36
37 #define MAX_SOCKS 1024
38 #define BUF_SIZE 1000
39
40 struct socket sockets[MAX_SOCKS];
41
42 void socket_appcall(void);
43 #ifndef UIP_APPCALL
44 #define UIP_APPCALL socket_appcall
45 #endif /* UIP_APPCALL */
46
47
48 static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
49 static void periodic_caller(int timer_id, void * arg);
50
51 void init_socket_layer() {
52         
53    int i = 0;
54    bool iflag;
55
56    
57    for (i = 0; i < MAX_SOCKS; i++) {
58       sockets[i].in_use = 0;
59       sockets[i].send_buf = NULL;
60       sockets[i].recv_buf = NULL;
61       sockets[i].state = CLOSED;
62    }
63
64     //initiate uIP
65     uip_init();
66     uip_arp_init();
67         
68     //setup device driver 
69     Init_Ne2k(&Packet_Received); 
70
71     iflag = Begin_Int_Atomic();
72     Start_Timer(2, periodic_caller, NULL);
73     End_Int_Atomic(iflag);
74 }
75
76 void set_ip_addr(uchar_t addr[4]) {
77   uip_ipaddr_t ipaddr;
78   uip_ipaddr(ipaddr, addr[0], addr[1], addr[2], addr[3]);  /* Local IP address */
79   uip_sethostaddr(ipaddr);
80 }
81
82 static int allocate_socket_fd() {
83   int i = 0;
84   
85   for (i = 0; i < MAX_SOCKS; i++) {
86     if (sockets[i].in_use == 0) {
87       sockets[i].in_use = 1;
88       sockets[i].send_buf = create_ring_buffer(BUF_SIZE);
89       if (sockets[i].send_buf == NULL)
90                 return -1;
91       sockets[i].recv_buf = create_ring_buffer(BUF_SIZE);
92       if (sockets[i].recv_buf == NULL){
93                 free_ring_buffer(sockets[i].send_buf);
94                 return -1;
95       }
96       return i;
97     }
98   }
99
100   return -1;
101 }
102
103 static int release_socket_fd(int sockfd){
104        if (sockfd >= 0 && sockfd < MAX_SOCKS){
105                 sockets[sockfd].in_use = 0;
106                 free_ring_buffer(sockets[sockfd].send_buf);
107                 free_ring_buffer(sockets[sockfd].recv_buf);
108                 sockets[sockfd].send_buf = NULL;
109                 sockets[sockfd].recv_buf = NULL;
110                 sockets[sockfd].state = CLOSED;
111        }
112
113         return 0;
114 }
115
116
117 struct socket * get_socket_from_fd(int fd) {
118   return &(sockets[fd]);
119 }
120
121
122 static void periodic_caller(int timer_id, void * arg) {
123   int i;
124   //handle the periodic calls of uIP
125   
126   //PrintBoth("Timer CALLBACK handler\n");
127
128   for(i = 0; i < UIP_CONNS; ++i) {
129     uip_periodic(i);
130     if(uip_len > 0) {
131       //devicedriver_send();
132       PrintBoth("Sending Packet\n");
133       NE2K_Transmit(uip_len);
134     }
135   }
136   for(i = 0; i < UIP_UDP_CONNS; i++) {
137     uip_udp_periodic(i);
138     if(uip_len > 0) {
139     //devicedriver_send();
140       NE2K_Transmit(uip_len);
141     }
142   }
143 }
144
145
146 int connect(const uchar_t ip_addr[4], ushort_t port) {
147   int sockfd = -1;
148   sockfd = allocate_socket_fd();
149   static uip_ipaddr_t ipaddr;
150   
151   if (sockfd == -1) {
152     return -1;
153   }
154
155   uip_ipaddr(&ipaddr, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);  
156   
157   sockets[sockfd].con = uip_connect(&ipaddr, htons(port));
158
159
160   if (sockets[sockfd].con == NULL){
161     release_socket_fd(sockfd);
162     return -1;
163   }
164
165
166   PrintBoth("Connection start\n");
167   Wait(&(sockets[sockfd].recv_wait_queue));
168   
169     
170   PrintBoth("Connected\n");
171
172
173
174
175   return sockfd;
176 }
177
178 int recv(int sockfd, void * buf, uint_t len){
179   uint_t recvlen;
180
181   struct socket *sock = get_socket_from_fd(sockfd);
182
183
184   // here we need some lock mechnism, just disable interrupt may not work properly because recv() will be run as a kernel thread 
185 buf_read:
186   recvlen = rb_read(sock->recv_buf, buf, len);
187
188   if (recvlen == 0){
189         Wait(&(sock->recv_wait_queue));
190         goto buf_read;
191   }
192
193   return recvlen;
194 }
195
196
197
198 // a series of utilities to handle conncetion states
199 static void connected(int sockfd) {
200   struct socket * sock = get_socket_from_fd(sockfd);
201
202   PrintBoth("Connected Interrupt\n");
203
204   sock->state = ESTABLISHED;
205
206   Wake_Up(&(sock->recv_wait_queue));
207 }
208
209 static void closed(int sockfd){
210
211 }
212
213 static void acked(int sockfd){
214
215 }
216
217 static void newdata(int sockfd){
218   uint_t len;
219   char *dataptr;
220   uint_t wrlen;
221   struct socket *sock;
222     
223   len = uip_datalen();
224   dataptr = (char *)uip_appdata;
225
226   if (len == 0)
227         return;
228
229   sock = get_socket_from_fd(sockfd);
230
231   wrlen = rb_write(sock->recv_buf, dataptr, len);
232
233   if (wrlen < len){ //write error, what should I do?
234         return;
235   }
236
237   Wake_Up(&(sock->recv_wait_queue));
238
239   return;    
240
241 }
242
243 // not finished yet
244 static void send_to_driver(int sockfd) {
245
246   PrintBoth("Sending data to driver\n");
247
248 }
249
250
251
252 int send(int sockfd, void * buf, uint_t len) {
253   struct socket * sock = get_socket_from_fd(sockfd);
254   //int mss = uip_mss();
255   //int pending_bytes = rb_data_len(sock->send_buf);
256   //int len = (mss < pending_bytes) ? mss: pending_bytes;
257   int bytes_read = 0;
258   uchar_t * send_buf = uip_appdata;
259   
260   bytes_read = rb_peek(sock->send_buf, send_buf, len);
261
262   if (bytes_read == 0) {
263     // no packet for send
264     return -1;
265   }
266
267   uip_send(send_buf, len);
268
269   return len;
270 }
271
272
273
274 //get the socket id by the local tcp port
275 static int get_socket_from_port(ushort_t lport) {
276   int i;
277   
278
279   for (i = 0; i < MAX_SOCKS; i++){
280     if (sockets[i].con->lport == lport) {
281       return i;
282     }
283   }
284   
285   return -1;
286 }
287
288
289
290 void socket_appcall(void) {
291
292   int sockfd; 
293   
294   sockfd = get_socket_from_port(uip_conn->lport);
295
296   PrintBoth("Appcall\n");
297
298   
299   if (sockfd == -1) {
300     return;
301   }
302
303   if (uip_connected()) {
304     connected(sockfd);
305
306   }
307   
308   if (uip_closed() ||uip_aborted() ||uip_timedout()) {
309      closed(sockfd);
310      return;
311   }
312   
313   if (uip_acked()) {
314      acked(sockfd);
315   }
316   
317   if (uip_newdata()) {
318      newdata(sockfd);
319   }
320   
321   if (uip_rexmit() ||
322       uip_newdata() ||
323       uip_acked() ||
324       uip_connected() ||
325       uip_poll()) {
326     send_to_driver(sockfd);
327   }
328 }
329
330
331
332
333 static int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
334   //int i;
335   uip_len = info->size; 
336
337   //  for (i = 0; i < info->size; i++) {
338   //  uip_buf[i] = *(pkt + i);
339   //}
340
341   PrintBoth("Packet REceived\n");
342
343   memcpy(uip_buf, pkt, uip_len);
344
345
346   Free(pkt);
347
348   if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
349     PrintBoth("ARP PACKET\n");
350
351     uip_arp_arpin();
352
353
354     if (uip_len > 0) {
355       PrintBoth("Transmitting\n");
356       NE2K_Transmit(uip_len);
357     }   
358                         
359
360   } else {
361     PrintBoth("Data PACKET\n");
362     uip_arp_ipin();
363     uip_input();
364
365
366     if (uip_len > 0) {
367       PrintBoth("Transmitting\n");
368       uip_arp_out();
369       NE2K_Transmit(uip_len);
370     }
371     
372   }
373
374   return 0;
375 }
376
377
378 #endif  /* UIP */