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 / 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     sys_mbox_fetch(mbox, (void *)&msg);
265     switch (msg->type) {
266 #if LWIP_NETCONN
267     case TCPIP_MSG_API:
268       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
269       msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
270       break;
271 #endif /* LWIP_NETCONN */
272
273     case TCPIP_MSG_INPKT:
274       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
275 #if LWIP_ARP
276       if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) {
277         ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
278       } else
279 #endif /* LWIP_ARP */
280       { ip_input(msg->msg.inp.p, msg->msg.inp.netif);
281       }
282       memp_free(MEMP_TCPIP_MSG_INPKT, msg);
283       break;
284
285 #if LWIP_NETIF_API
286     case TCPIP_MSG_NETIFAPI:
287       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
288       msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
289       break;
290 #endif /* LWIP_NETIF_API */
291
292     case TCPIP_MSG_CALLBACK:
293       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
294       msg->msg.cb.f(msg->msg.cb.ctx);
295       memp_free(MEMP_TCPIP_MSG_API, msg);
296       break;
297
298     case TCPIP_MSG_TIMEOUT:
299       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
300
301       if(msg->msg.tmo.msecs != 0xffffffff)
302         sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
303       else
304         sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg);
305       memp_free(MEMP_TCPIP_MSG_API, msg);
306       break;
307
308     default:
309       break;
310     }
311   }
312 }
313
314 /**
315  * Pass a received packet to tcpip_thread for input processing
316  *
317  * @param p the received packet, p->payload pointing to the Ethernet header or
318  *          to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
319  * @param inp the network interface on which the packet was received
320  */
321 err_t
322 tcpip_input(struct pbuf *p, struct netif *inp)
323 {
324   struct tcpip_msg *msg;
325
326   if (mbox != SYS_MBOX_NULL) {
327     msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
328     if (msg == NULL) {
329       return ERR_MEM;
330     }
331
332     msg->type = TCPIP_MSG_INPKT;
333     msg->msg.inp.p = p;
334     msg->msg.inp.netif = inp;
335     if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
336       memp_free(MEMP_TCPIP_MSG_INPKT, msg);
337       return ERR_MEM;
338     }
339     return ERR_OK;
340   }
341   return ERR_VAL;
342 }
343
344 /**
345  * Call a specific function in the thread context of
346  * tcpip_thread for easy access synchronization.
347  * A function called in that way may access lwIP core code
348  * without fearing concurrent access.
349  *
350  * @param f the function to call
351  * @param ctx parameter passed to f
352  * @param block 1 to block until the request is posted, 0 to non-blocking mode
353  * @return ERR_OK if the function was called, another err_t if not
354  */
355 err_t
356 tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
357 {
358   struct tcpip_msg *msg;
359
360   if (mbox != SYS_MBOX_NULL) {
361     msg = memp_malloc(MEMP_TCPIP_MSG_API);
362     if (msg == NULL) {
363       return ERR_MEM;
364     }
365
366     msg->type = TCPIP_MSG_CALLBACK;
367     msg->msg.cb.f = f;
368     msg->msg.cb.ctx = ctx;
369     if (block) {
370       sys_mbox_post(mbox, msg);
371     } else {
372       if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
373         memp_free(MEMP_TCPIP_MSG_API, msg);
374         return ERR_MEM;
375       }
376     }
377     return ERR_OK;
378   }
379   return ERR_VAL;
380 }
381
382 err_t
383 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
384 {
385   struct tcpip_msg *msg;
386
387   if (mbox != SYS_MBOX_NULL) {
388     msg = memp_malloc(MEMP_TCPIP_MSG_API);
389     if (msg == NULL) {
390       return ERR_MEM;
391     }
392
393     msg->type = TCPIP_MSG_TIMEOUT;
394     msg->msg.tmo.msecs = msecs;
395     msg->msg.tmo.h = h;
396     msg->msg.tmo.arg = arg;
397     sys_mbox_post(mbox, msg);
398     return ERR_OK;
399   }
400   return ERR_VAL;
401 }
402
403 #if LWIP_NETCONN
404 /**
405  * Call the lower part of a netconn_* function
406  * This function is then running in the thread context
407  * of tcpip_thread and has exclusive access to lwIP core code.
408  *
409  * @param apimsg a struct containing the function to call and its parameters
410  * @return ERR_OK if the function was called, another err_t if not
411  */
412 err_t
413 tcpip_apimsg(struct api_msg *apimsg)
414 {
415   struct tcpip_msg msg;
416   
417   if (mbox != SYS_MBOX_NULL) {
418     msg.type = TCPIP_MSG_API;
419     msg.msg.apimsg = apimsg;
420     sys_mbox_post(mbox, &msg);
421     sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);
422     return ERR_OK;
423   }
424   return ERR_VAL;
425 }
426
427 #if LWIP_TCPIP_CORE_LOCKING
428 /**
429  * Call the lower part of a netconn_* function
430  * This function has exclusive access to lwIP core code by locking it
431  * before the function is called.
432  *
433  * @param apimsg a struct containing the function to call and its parameters
434  * @return ERR_OK (only for compatibility fo tcpip_apimsg())
435  */
436 err_t
437 tcpip_apimsg_lock(struct api_msg *apimsg)
438 {
439   LOCK_TCPIP_CORE();
440   apimsg->function(&(apimsg->msg));
441   UNLOCK_TCPIP_CORE();
442   return ERR_OK;
443
444 }
445 #endif /* LWIP_TCPIP_CORE_LOCKING */
446 #endif /* LWIP_NETCONN */
447
448 #if LWIP_NETIF_API
449 #if !LWIP_TCPIP_CORE_LOCKING
450 /**
451  * Much like tcpip_apimsg, but calls the lower part of a netifapi_*
452  * function.
453  *
454  * @param netifapimsg a struct containing the function to call and its parameters
455  * @return error code given back by the function that was called
456  */
457 err_t
458 tcpip_netifapi(struct netifapi_msg* netifapimsg)
459 {
460   struct tcpip_msg msg;
461   
462   if (mbox != SYS_MBOX_NULL) {
463     netifapimsg->msg.sem = sys_sem_new(0);
464     if (netifapimsg->msg.sem == SYS_SEM_NULL) {
465       netifapimsg->msg.err = ERR_MEM;
466       return netifapimsg->msg.err;
467     }
468     
469     msg.type = TCPIP_MSG_NETIFAPI;
470     msg.msg.netifapimsg = netifapimsg;
471     sys_mbox_post(mbox, &msg);
472     sys_sem_wait(netifapimsg->msg.sem);
473     sys_sem_free(netifapimsg->msg.sem);
474     return netifapimsg->msg.err;
475   }
476   return ERR_VAL;
477 }
478 #else /* !LWIP_TCPIP_CORE_LOCKING */
479 /**
480  * Call the lower part of a netifapi_* function
481  * This function has exclusive access to lwIP core code by locking it
482  * before the function is called.
483  *
484  * @param netifapimsg a struct containing the function to call and its parameters
485  * @return ERR_OK (only for compatibility fo tcpip_netifapi())
486  */
487 err_t
488 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
489 {
490   LOCK_TCPIP_CORE();  
491   netifapimsg->function(&(netifapimsg->msg));
492   UNLOCK_TCPIP_CORE();
493   return netifapimsg->msg.err;
494 }
495 #endif /* !LWIP_TCPIP_CORE_LOCKING */
496 #endif /* LWIP_NETIF_API */
497
498 /**
499  * Initialize this module:
500  * - initialize all sub modules
501  * - start the tcpip_thread
502  *
503  * @param initfunc a function to call when tcpip_thread is running and finished initializing
504  * @param arg argument to pass to initfunc
505  */
506 void
507 tcpip_init(void (* initfunc)(void *), void *arg)
508 {
509   lwip_init();
510
511   tcpip_init_done = initfunc;
512   tcpip_init_done_arg = arg;
513   mbox = sys_mbox_new(TCPIP_MBOX_SIZE);
514 #if LWIP_TCPIP_CORE_LOCKING
515   lock_tcpip_core = sys_sem_new(1);
516 #endif /* LWIP_TCPIP_CORE_LOCKING */
517
518   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
519 }
520
521 #endif /* !NO_SYS */