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 / lwip / api / tcpip.c
1 /**
2  * @file
3  * Sequential API Main thread module
4  *
5  */
6
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38
39 #include "lwip/opt.h"
40
41 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */
42
43 #include "lwip/sys.h"
44 #include "lwip/memp.h"
45 #include "lwip/pbuf.h"
46 #include "lwip/ip_frag.h"
47 #include "lwip/tcp.h"
48 #include "lwip/autoip.h"
49 #include "lwip/dhcp.h"
50 #include "lwip/igmp.h"
51 #include "lwip/dns.h"
52 #include "lwip/tcpip.h"
53 #include "lwip/init.h"
54 #include "netif/etharp.h"
55 #include "netif/ppp_oe.h"
56
57 /* global variables */
58 static void (* tcpip_init_done)(void *arg);
59 static void *tcpip_init_done_arg;
60 static sys_mbox_t mbox = SYS_MBOX_NULL;
61
62 #if LWIP_TCPIP_CORE_LOCKING
63 /** The global semaphore to lock the stack. */
64 sys_sem_t lock_tcpip_core;
65 #endif /* LWIP_TCPIP_CORE_LOCKING */
66
67 #if LWIP_TCP
68 /* global variable that shows if the tcp timer is currently scheduled or not */
69 static int tcpip_tcp_timer_active;
70
71 /**
72  * Timer callback function that calls tcp_tmr() and reschedules itself.
73  *
74  * @param arg unused argument
75  */
76 static void
77 tcpip_tcp_timer(void *arg)
78 {
79   LWIP_UNUSED_ARG(arg);
80
81   /* call TCP timer handler */
82   tcp_tmr();
83   /* timer still needed? */
84   if (tcp_active_pcbs || tcp_tw_pcbs) {
85     /* restart timer */
86     sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
87   } else {
88     /* disable timer */
89     tcpip_tcp_timer_active = 0;
90   }
91 }
92
93 #if !NO_SYS
94 /**
95  * Called from TCP_REG when registering a new PCB:
96  * the reason is to have the TCP timer only running when
97  * there are active (or time-wait) PCBs.
98  */
99 void
100 tcp_timer_needed(void)
101 {
102   /* timer is off but needed again? */
103   if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
104     /* enable and start timer */
105     tcpip_tcp_timer_active = 1;
106     sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
107   }
108 }
109 #endif /* !NO_SYS */
110 #endif /* LWIP_TCP */
111
112 #if IP_REASSEMBLY
113 /**
114  * Timer callback function that calls ip_reass_tmr() and reschedules itself.
115  *
116  * @param arg unused argument
117  */
118 static void
119 ip_reass_timer(void *arg)
120 {
121   LWIP_UNUSED_ARG(arg);
122   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
123   ip_reass_tmr();
124   sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
125 }
126 #endif /* IP_REASSEMBLY */
127
128 #if LWIP_ARP
129 /**
130  * Timer callback function that calls etharp_tmr() and reschedules itself.
131  *
132  * @param arg unused argument
133  */
134 static void
135 arp_timer(void *arg)
136 {
137   LWIP_UNUSED_ARG(arg);
138   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n"));
139   etharp_tmr();
140   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
141 }
142 #endif /* LWIP_ARP */
143
144 #if LWIP_DHCP
145 /**
146  * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
147  *
148  * @param arg unused argument
149  */
150 static void
151 dhcp_timer_coarse(void *arg)
152 {
153   LWIP_UNUSED_ARG(arg);
154   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
155   dhcp_coarse_tmr();
156   sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
157 }
158
159 /**
160  * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
161  *
162  * @param arg unused argument
163  */
164 static void
165 dhcp_timer_fine(void *arg)
166 {
167   LWIP_UNUSED_ARG(arg);
168   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
169   dhcp_fine_tmr();
170   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
171 }
172 #endif /* LWIP_DHCP */
173
174 #if LWIP_AUTOIP
175 /**
176  * Timer callback function that calls autoip_tmr() and reschedules itself.
177  *
178  * @param arg unused argument
179  */
180 static void
181 autoip_timer(void *arg)
182 {
183   LWIP_UNUSED_ARG(arg);
184   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n"));
185   autoip_tmr();
186   sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
187 }
188 #endif /* LWIP_AUTOIP */
189
190 #if LWIP_IGMP
191 /**
192  * Timer callback function that calls igmp_tmr() and reschedules itself.
193  *
194  * @param arg unused argument
195  */
196 static void
197 igmp_timer(void *arg)
198 {
199   LWIP_UNUSED_ARG(arg);
200   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n"));
201   igmp_tmr();
202   sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
203 }
204 #endif /* LWIP_IGMP */
205
206 #if LWIP_DNS
207 /**
208  * Timer callback function that calls dns_tmr() and reschedules itself.
209  *
210  * @param arg unused argument
211  */
212 static void
213 dns_timer(void *arg)
214 {
215   LWIP_UNUSED_ARG(arg);
216   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n"));
217   dns_tmr();
218   sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
219 }
220 #endif /* LWIP_DNS */
221
222 /**
223  * The main lwIP thread. This thread has exclusive access to lwIP core functions
224  * (unless access to them is not locked). Other threads communicate with this
225  * thread using message boxes.
226  *
227  * It also starts all the timers to make sure they are running in the right
228  * thread context.
229  *
230  * @param arg unused argument
231  */
232 static void
233 tcpip_thread(void *arg)
234 {
235   struct tcpip_msg *msg;
236   LWIP_UNUSED_ARG(arg);
237
238 #if IP_REASSEMBLY
239   sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
240 #endif /* IP_REASSEMBLY */
241 #if LWIP_ARP
242   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
243 #endif /* LWIP_ARP */
244 #if LWIP_DHCP
245   sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
246   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
247 #endif /* LWIP_DHCP */
248 #if LWIP_AUTOIP
249   sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
250 #endif /* LWIP_AUTOIP */
251 #if LWIP_IGMP
252   sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
253 #endif /* LWIP_IGMP */
254 #if LWIP_DNS
255   sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
256 #endif /* LWIP_DNS */
257
258   if (tcpip_init_done != NULL) {
259     tcpip_init_done(tcpip_init_done_arg);
260   }
261
262   LOCK_TCPIP_CORE();
263   while (1) {                          /* MAIN Loop */
264
265     PrintBoth("In tcp_thread: main loop\n");    
266
267     sys_mbox_fetch(mbox, (void *)&msg);
268
269     switch (msg->type) {
270 #if LWIP_NETCONN
271     case TCPIP_MSG_API:
272       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
273       msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
274       break;
275 #endif /* LWIP_NETCONN */
276
277     case TCPIP_MSG_INPKT:
278       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
279 #if LWIP_ARP
280       if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) {
281         ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
282       } else
283 #endif /* LWIP_ARP */
284       { ip_input(msg->msg.inp.p, msg->msg.inp.netif);
285       }
286       memp_free(MEMP_TCPIP_MSG_INPKT, msg);
287       break;
288
289 #if LWIP_NETIF_API
290     case TCPIP_MSG_NETIFAPI:
291       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
292       msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
293       break;
294 #endif /* LWIP_NETIF_API */
295
296     case TCPIP_MSG_CALLBACK:
297       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
298       msg->msg.cb.f(msg->msg.cb.ctx);
299       memp_free(MEMP_TCPIP_MSG_API, msg);
300       break;
301
302     case TCPIP_MSG_TIMEOUT:
303       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
304
305       if(msg->msg.tmo.msecs != 0xffffffff)
306         sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
307       else
308         sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg);
309       memp_free(MEMP_TCPIP_MSG_API, msg);
310       break;
311
312     default:
313       break;
314     }
315   }
316 }
317
318 /**
319  * Pass a received packet to tcpip_thread for input processing
320  *
321  * @param p the received packet, p->payload pointing to the Ethernet header or
322  *          to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
323  * @param inp the network interface on which the packet was received
324  */
325 err_t
326 tcpip_input(struct pbuf *p, struct netif *inp)
327 {
328   struct tcpip_msg *msg;
329
330   if (mbox != SYS_MBOX_NULL) {
331     msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
332     if (msg == NULL) {
333       return ERR_MEM;
334     }
335
336     msg->type = TCPIP_MSG_INPKT;
337     msg->msg.inp.p = p;
338     msg->msg.inp.netif = inp;
339     if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
340       memp_free(MEMP_TCPIP_MSG_INPKT, msg);
341       return ERR_MEM;
342     }
343     return ERR_OK;
344   }
345   return ERR_VAL;
346 }
347
348 /**
349  * Call a specific function in the thread context of
350  * tcpip_thread for easy access synchronization.
351  * A function called in that way may access lwIP core code
352  * without fearing concurrent access.
353  *
354  * @param f the function to call
355  * @param ctx parameter passed to f
356  * @param block 1 to block until the request is posted, 0 to non-blocking mode
357  * @return ERR_OK if the function was called, another err_t if not
358  */
359 err_t
360 tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
361 {
362   struct tcpip_msg *msg;
363
364   if (mbox != SYS_MBOX_NULL) {
365     msg = memp_malloc(MEMP_TCPIP_MSG_API);
366     if (msg == NULL) {
367       return ERR_MEM;
368     }
369
370     msg->type = TCPIP_MSG_CALLBACK;
371     msg->msg.cb.f = f;
372     msg->msg.cb.ctx = ctx;
373     if (block) {
374       sys_mbox_post(mbox, msg);
375     } else {
376       if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
377         memp_free(MEMP_TCPIP_MSG_API, msg);
378         return ERR_MEM;
379       }
380     }
381     return ERR_OK;
382   }
383   return ERR_VAL;
384 }
385
386 err_t
387 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
388 {
389   struct tcpip_msg *msg;
390
391   if (mbox != SYS_MBOX_NULL) {
392     msg = memp_malloc(MEMP_TCPIP_MSG_API);
393     if (msg == NULL) {
394       return ERR_MEM;
395     }
396
397     msg->type = TCPIP_MSG_TIMEOUT;
398     msg->msg.tmo.msecs = msecs;
399     msg->msg.tmo.h = h;
400     msg->msg.tmo.arg = arg;
401     sys_mbox_post(mbox, msg);
402     return ERR_OK;
403   }
404   return ERR_VAL;
405 }
406
407 #if LWIP_NETCONN
408 /**
409  * Call the lower part of a netconn_* function
410  * This function is then running in the thread context
411  * of tcpip_thread and has exclusive access to lwIP core code.
412  *
413  * @param apimsg a struct containing the function to call and its parameters
414  * @return ERR_OK if the function was called, another err_t if not
415  */
416 err_t
417 tcpip_apimsg(struct api_msg *apimsg)
418 {
419   struct tcpip_msg msg;
420   
421   if (mbox != SYS_MBOX_NULL) {
422     msg.type = TCPIP_MSG_API;
423     msg.msg.apimsg = apimsg;
424     sys_mbox_post(mbox, &msg);
425     sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);
426     return ERR_OK;
427   }
428   return ERR_VAL;
429 }
430
431 #if LWIP_TCPIP_CORE_LOCKING
432 /**
433  * Call the lower part of a netconn_* function
434  * This function has exclusive access to lwIP core code by locking it
435  * before the function is called.
436  *
437  * @param apimsg a struct containing the function to call and its parameters
438  * @return ERR_OK (only for compatibility fo tcpip_apimsg())
439  */
440 err_t
441 tcpip_apimsg_lock(struct api_msg *apimsg)
442 {
443   LOCK_TCPIP_CORE();
444   apimsg->function(&(apimsg->msg));
445   UNLOCK_TCPIP_CORE();
446   return ERR_OK;
447
448 }
449 #endif /* LWIP_TCPIP_CORE_LOCKING */
450 #endif /* LWIP_NETCONN */
451
452 #if LWIP_NETIF_API
453 #if !LWIP_TCPIP_CORE_LOCKING
454 /**
455  * Much like tcpip_apimsg, but calls the lower part of a netifapi_*
456  * function.
457  *
458  * @param netifapimsg a struct containing the function to call and its parameters
459  * @return error code given back by the function that was called
460  */
461 err_t
462 tcpip_netifapi(struct netifapi_msg* netifapimsg)
463 {
464   struct tcpip_msg msg;
465   
466   if (mbox != SYS_MBOX_NULL) {
467     netifapimsg->msg.sem = sys_sem_new(0);
468     if (netifapimsg->msg.sem == SYS_SEM_NULL) {
469       netifapimsg->msg.err = ERR_MEM;
470       return netifapimsg->msg.err;
471     }
472     
473     msg.type = TCPIP_MSG_NETIFAPI;
474     msg.msg.netifapimsg = netifapimsg;
475     sys_mbox_post(mbox, &msg);
476     sys_sem_wait(netifapimsg->msg.sem);
477     sys_sem_free(netifapimsg->msg.sem);
478     return netifapimsg->msg.err;
479   }
480   return ERR_VAL;
481 }
482 #else /* !LWIP_TCPIP_CORE_LOCKING */
483 /**
484  * Call the lower part of a netifapi_* function
485  * This function has exclusive access to lwIP core code by locking it
486  * before the function is called.
487  *
488  * @param netifapimsg a struct containing the function to call and its parameters
489  * @return ERR_OK (only for compatibility fo tcpip_netifapi())
490  */
491 err_t
492 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
493 {
494   LOCK_TCPIP_CORE();  
495   netifapimsg->function(&(netifapimsg->msg));
496   UNLOCK_TCPIP_CORE();
497   return netifapimsg->msg.err;
498 }
499 #endif /* !LWIP_TCPIP_CORE_LOCKING */
500 #endif /* LWIP_NETIF_API */
501
502 /**
503  * Initialize this module:
504  * - initialize all sub modules
505  * - start the tcpip_thread
506  *
507  * @param initfunc a function to call when tcpip_thread is running and finished initializing
508  * @param arg argument to pass to initfunc
509  */
510 void
511 tcpip_init(void (* initfunc)(void *), void *arg)
512 {
513   lwip_init();
514
515   tcpip_init_done = initfunc;
516   tcpip_init_done_arg = arg;
517   mbox = sys_mbox_new(TCPIP_MBOX_SIZE);
518 #if LWIP_TCPIP_CORE_LOCKING
519   lock_tcpip_core = sys_sem_new(1);
520 #endif /* LWIP_TCPIP_CORE_LOCKING */
521
522   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
523 }
524
525 #endif /* !NO_SYS */