2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
37 #include "lwip/memp.h"
38 #include "lwip/pbuf.h"
40 #include "netif/etharp.h"
43 #include "lwip/ip_frag.h"
47 #include "lwip/tcpip.h"
48 #include "lwip/igmp.h"
52 static void (* tcpip_init_done)(void *arg) = NULL;
53 static void *tcpip_init_done_arg = NULL;
54 static sys_mbox_t mbox = SYS_MBOX_NULL;
56 #if LWIP_TCPIP_CORE_LOCKING
57 /** The global semaphore to lock the stack. */
58 sys_sem_t lock_tcpip_core = 0;
59 #endif /* LWIP_TCPIP_CORE_LOCKING */
62 static int tcpip_tcp_timer_active = 0;
65 tcpip_tcp_timer(void *arg)
69 /* call TCP timer handler */
71 /* timer still needed? */
72 if (tcp_active_pcbs || tcp_tw_pcbs) {
74 sys_timeout( TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
77 tcpip_tcp_timer_active = 0;
83 tcp_timer_needed(void)
85 /* timer is off but needed again? */
86 if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
87 /* enable and start timer */
88 tcpip_tcp_timer_active = 1;
89 sys_timeout( TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
100 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
102 sys_timeout( IP_TMR_INTERVAL, ip_timer, NULL);
104 #endif /* IP_REASSEMBLY */
110 LWIP_UNUSED_ARG(arg);
111 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n"));
113 sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL);
115 #endif /* LWIP_ARP */
119 dhcp_timer_coarse(void *arg)
121 LWIP_UNUSED_ARG(arg);
122 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
124 sys_timeout(DHCP_COARSE_TIMER_SECS*1000, dhcp_timer_coarse, NULL);
128 dhcp_timer_fine(void *arg)
130 LWIP_UNUSED_ARG(arg);
131 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
133 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
135 #endif /* LWIP_DHCP */
139 igmp_timer(void *arg)
141 LWIP_UNUSED_ARG(arg);
142 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n"));
144 sys_timeout( IGMP_TMR_INTERVAL, igmp_timer, NULL);
146 #endif /* LWIP_IGMP */
148 #if ETHARP_TCPIP_ETHINPUT
150 ethernet_input(struct pbuf *p, struct netif *netif)
152 struct eth_hdr* ethhdr;
154 /* points to packet payload, which starts with an Ethernet header */
157 switch (htons(ethhdr->type)) {
160 #if ETHARP_TRUST_IP_MAC
161 /* update ARP table */
162 etharp_ip_input( netif, p);
164 /* skip Ethernet header */
165 if(pbuf_header(p, -(s16_t)sizeof(struct eth_hdr))) {
166 LWIP_ASSERT("Can't move over header in packet", 0);
171 /* pass to IP layer */
176 /* pass p to ARP module */
177 etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
186 #endif /* ETHARP_TCPIP_ETHINPUT */
189 tcpip_thread(void *arg)
191 struct tcpip_msg *msg;
192 LWIP_UNUSED_ARG(arg);
195 sys_timeout( IP_TMR_INTERVAL, ip_timer, NULL);
196 #endif /* IP_REASSEMBLY */
198 sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL);
199 #endif /* LWIP_ARP */
201 sys_timeout( DHCP_COARSE_TIMER_SECS*1000, dhcp_timer_coarse, NULL);
202 sys_timeout( DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
203 #endif /* LWIP_DHCP */
205 if (tcpip_init_done != NULL) {
206 tcpip_init_done(tcpip_init_done_arg);
211 sys_timeout( IGMP_TMR_INTERVAL, igmp_timer, NULL);
212 #endif /* LWIP_IGMP */
215 while (1) { /* MAIN Loop */
216 sys_mbox_fetch(mbox, (void *)&msg);
219 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
220 msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
223 #if ETHARP_TCPIP_INPUT
224 case TCPIP_MSG_INPUT:
225 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));
226 ip_input(msg->msg.inp.p, msg->msg.inp.netif);
227 memp_free(MEMP_TCPIP_MSG, msg);
229 #endif /* ETHARP_TCPIP_INPUT */
231 #if ETHARP_TCPIP_ETHINPUT
232 case TCPIP_MSG_ETHINPUT:
233 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Ethernet packet %p\n", (void *)msg));
234 ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
235 memp_free(MEMP_TCPIP_MSG, msg);
237 #endif /* ETHARP_TCPIP_ETHINPUT */
240 case TCPIP_MSG_NETIFAPI:
241 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
242 netifapi_msg_input(msg->msg.netifapimsg);
244 #endif /* LWIP_NETIF_API */
246 case TCPIP_MSG_CALLBACK:
247 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
248 msg->msg.cb.f(msg->msg.cb.ctx);
249 memp_free(MEMP_TCPIP_MSG, msg);
257 #if ETHARP_TCPIP_INPUT
259 tcpip_input(struct pbuf *p, struct netif *inp)
261 struct tcpip_msg *msg;
263 if (mbox != SYS_MBOX_NULL) {
264 msg = memp_malloc(MEMP_TCPIP_MSG);
269 msg->type = TCPIP_MSG_INPUT;
271 msg->msg.inp.netif = inp;
272 sys_mbox_post(mbox, msg);
277 #endif /* ETHARP_TCPIP_INPUT */
279 #if ETHARP_TCPIP_ETHINPUT
281 tcpip_ethinput(struct pbuf *p, struct netif *inp)
283 struct tcpip_msg *msg;
285 if (mbox != SYS_MBOX_NULL) {
286 msg = memp_malloc(MEMP_TCPIP_MSG);
291 msg->type = TCPIP_MSG_ETHINPUT;
293 msg->msg.inp.netif = inp;
294 sys_mbox_post(mbox, msg);
299 #endif /* ETHARP_TCPIP_ETHINPUT */
302 tcpip_callback(void (*f)(void *ctx), void *ctx)
304 struct tcpip_msg *msg;
306 if (mbox != SYS_MBOX_NULL) {
307 msg = memp_malloc(MEMP_TCPIP_MSG);
312 msg->type = TCPIP_MSG_CALLBACK;
314 msg->msg.cb.ctx = ctx;
315 sys_mbox_post(mbox, msg);
322 tcpip_apimsg(struct api_msg *apimsg)
324 struct tcpip_msg msg;
326 if (mbox != SYS_MBOX_NULL) {
327 msg.type = TCPIP_MSG_API;
328 msg.msg.apimsg = apimsg;
329 sys_mbox_post(mbox, &msg);
330 sys_arch_mbox_fetch(apimsg->msg.conn->mbox, NULL, 0);
336 #if LWIP_TCPIP_CORE_LOCKING
338 tcpip_apimsg_lock(struct api_msg *apimsg)
341 apimsg->function(&(apimsg->msg));
346 #endif /* LWIP_TCPIP_CORE_LOCKING */
349 err_t tcpip_netifapi(struct netifapi_msg* netifapimsg)
351 struct tcpip_msg msg;
353 if (mbox != SYS_MBOX_NULL) {
354 netifapimsg->sem = sys_sem_new(0);
355 if (netifapimsg->sem == SYS_SEM_NULL) {
356 netifapimsg->err = ERR_MEM;
357 return netifapimsg->err;
360 msg.type = TCPIP_MSG_NETIFAPI;
361 msg.msg.netifapimsg = netifapimsg;
362 sys_mbox_post(mbox, &msg);
363 sys_sem_wait(netifapimsg->sem);
364 sys_sem_free(netifapimsg->sem);
365 return netifapimsg->err;
369 #endif /* LWIP_NETIF_API */
372 tcpip_init(void (* initfunc)(void *), void *arg)
380 #endif /* LWIP_UDP */
383 #endif /* LWIP_TCP */
385 tcpip_init_done = initfunc;
386 tcpip_init_done_arg = arg;
387 mbox = sys_mbox_new();
388 #if LWIP_TCPIP_CORE_LOCKING
389 lock_tcpip_core = sys_sem_new(1);
390 #endif /* LWIP_TCPIP_CORE_LOCKING */
392 sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);