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.


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