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.


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