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.


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