A version of LWIP, provided for backwards compatibility.
Dependents: AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more
tcpip.c
00001 /** 00002 * @file 00003 * Sequential API Main thread module 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 #include "lwip/opt.h" 00040 00041 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */ 00042 00043 #include "lwip/sys.h" 00044 #include "lwip/memp.h" 00045 #include "lwip/pbuf.h" 00046 #include "lwip/ip_frag.h" 00047 #include "lwip/tcp.h" 00048 #include "lwip/autoip.h" 00049 #include "lwip/dhcp.h" 00050 #include "lwip/igmp.h" 00051 #include "lwip/dns.h" 00052 #include "lwip/tcpip.h" 00053 #include "lwip/init.h" 00054 #include "netif/etharp.h" 00055 #include "netif/ppp_oe.h" 00056 00057 /* global variables */ 00058 static void (* tcpip_init_done)(void *arg); 00059 static void *tcpip_init_done_arg; 00060 static sys_mbox_t mbox = SYS_MBOX_NULL; 00061 00062 #if LWIP_TCPIP_CORE_LOCKING 00063 /** The global semaphore to lock the stack. */ 00064 sys_sem_t lock_tcpip_core; 00065 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00066 00067 #if LWIP_TCP 00068 /* global variable that shows if the tcp timer is currently scheduled or not */ 00069 static int tcpip_tcp_timer_active; 00070 00071 /** 00072 * Timer callback function that calls tcp_tmr() and reschedules itself. 00073 * 00074 * @param arg unused argument 00075 */ 00076 static void 00077 tcpip_tcp_timer(void *arg) 00078 { 00079 LWIP_UNUSED_ARG(arg); 00080 00081 /* call TCP timer handler */ 00082 tcp_tmr(); 00083 /* timer still needed? */ 00084 if (tcp_active_pcbs || tcp_tw_pcbs) { 00085 /* restart timer */ 00086 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); 00087 } else { 00088 /* disable timer */ 00089 tcpip_tcp_timer_active = 0; 00090 } 00091 } 00092 00093 #if !NO_SYS 00094 /** 00095 * Called from TCP_REG when registering a new PCB: 00096 * the reason is to have the TCP timer only running when 00097 * there are active (or time-wait) PCBs. 00098 */ 00099 void 00100 tcp_timer_needed(void) 00101 { 00102 /* timer is off but needed again? */ 00103 if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { 00104 /* enable and start timer */ 00105 tcpip_tcp_timer_active = 1; 00106 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); 00107 } 00108 } 00109 #endif /* !NO_SYS */ 00110 #endif /* LWIP_TCP */ 00111 00112 #if IP_REASSEMBLY 00113 /** 00114 * Timer callback function that calls ip_reass_tmr() and reschedules itself. 00115 * 00116 * @param arg unused argument 00117 */ 00118 static void 00119 ip_reass_timer(void *arg) 00120 { 00121 LWIP_UNUSED_ARG(arg); 00122 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n")); 00123 ip_reass_tmr(); 00124 sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); 00125 } 00126 #endif /* IP_REASSEMBLY */ 00127 00128 #if LWIP_ARP 00129 /** 00130 * Timer callback function that calls etharp_tmr() and reschedules itself. 00131 * 00132 * @param arg unused argument 00133 */ 00134 static void 00135 arp_timer(void *arg) 00136 { 00137 LWIP_UNUSED_ARG(arg); 00138 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n")); 00139 etharp_tmr(); 00140 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 00141 } 00142 #endif /* LWIP_ARP */ 00143 00144 #if LWIP_DHCP 00145 /** 00146 * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. 00147 * 00148 * @param arg unused argument 00149 */ 00150 static void 00151 dhcp_timer_coarse(void *arg) 00152 { 00153 LWIP_UNUSED_ARG(arg); 00154 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); 00155 dhcp_coarse_tmr(); 00156 sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); 00157 } 00158 00159 /** 00160 * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. 00161 * 00162 * @param arg unused argument 00163 */ 00164 static void 00165 dhcp_timer_fine(void *arg) 00166 { 00167 LWIP_UNUSED_ARG(arg); 00168 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); 00169 dhcp_fine_tmr(); 00170 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); 00171 } 00172 #endif /* LWIP_DHCP */ 00173 00174 #if LWIP_AUTOIP 00175 /** 00176 * Timer callback function that calls autoip_tmr() and reschedules itself. 00177 * 00178 * @param arg unused argument 00179 */ 00180 static void 00181 autoip_timer(void *arg) 00182 { 00183 LWIP_UNUSED_ARG(arg); 00184 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n")); 00185 autoip_tmr(); 00186 sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); 00187 } 00188 #endif /* LWIP_AUTOIP */ 00189 00190 #if LWIP_IGMP 00191 /** 00192 * Timer callback function that calls igmp_tmr() and reschedules itself. 00193 * 00194 * @param arg unused argument 00195 */ 00196 static void 00197 igmp_timer(void *arg) 00198 { 00199 LWIP_UNUSED_ARG(arg); 00200 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n")); 00201 igmp_tmr(); 00202 sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); 00203 } 00204 #endif /* LWIP_IGMP */ 00205 00206 #if LWIP_DNS 00207 /** 00208 * Timer callback function that calls dns_tmr() and reschedules itself. 00209 * 00210 * @param arg unused argument 00211 */ 00212 static void 00213 dns_timer(void *arg) 00214 { 00215 LWIP_UNUSED_ARG(arg); 00216 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n")); 00217 dns_tmr(); 00218 sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); 00219 } 00220 #endif /* LWIP_DNS */ 00221 00222 /** 00223 * The main lwIP thread. This thread has exclusive access to lwIP core functions 00224 * (unless access to them is not locked). Other threads communicate with this 00225 * thread using message boxes. 00226 * 00227 * It also starts all the timers to make sure they are running in the right 00228 * thread context. 00229 * 00230 * @param arg unused argument 00231 */ 00232 static void 00233 tcpip_thread(void *arg) 00234 { 00235 struct tcpip_msg *msg; 00236 LWIP_UNUSED_ARG(arg); 00237 00238 #if IP_REASSEMBLY 00239 sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); 00240 #endif /* IP_REASSEMBLY */ 00241 #if LWIP_ARP 00242 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 00243 #endif /* LWIP_ARP */ 00244 #if LWIP_DHCP 00245 sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); 00246 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); 00247 #endif /* LWIP_DHCP */ 00248 #if LWIP_AUTOIP 00249 sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); 00250 #endif /* LWIP_AUTOIP */ 00251 #if LWIP_IGMP 00252 sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); 00253 #endif /* LWIP_IGMP */ 00254 #if LWIP_DNS 00255 sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); 00256 #endif /* LWIP_DNS */ 00257 00258 if (tcpip_init_done != NULL) { 00259 tcpip_init_done(tcpip_init_done_arg); 00260 } 00261 00262 LOCK_TCPIP_CORE(); 00263 while (1) { /* MAIN Loop */ 00264 sys_mbox_fetch(mbox, (void *)&msg); 00265 switch (msg->type) { 00266 #if LWIP_NETCONN 00267 case TCPIP_MSG_API: 00268 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); 00269 msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); 00270 break; 00271 #endif /* LWIP_NETCONN */ 00272 00273 case TCPIP_MSG_INPKT: 00274 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); 00275 #if LWIP_ARP 00276 if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) { 00277 ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); 00278 } else 00279 #endif /* LWIP_ARP */ 00280 { ip_input(msg->msg.inp.p, msg->msg.inp.netif); 00281 } 00282 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00283 break; 00284 00285 #if LWIP_NETIF_API 00286 case TCPIP_MSG_NETIFAPI: 00287 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); 00288 msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); 00289 break; 00290 #endif /* LWIP_NETIF_API */ 00291 00292 case TCPIP_MSG_CALLBACK: 00293 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); 00294 msg->msg.cb.f(msg->msg.cb.ctx); 00295 memp_free(MEMP_TCPIP_MSG_API, msg); 00296 break; 00297 00298 case TCPIP_MSG_TIMEOUT: 00299 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); 00300 00301 if(msg->msg.tmo.msecs != 0xffffffff) 00302 sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); 00303 else 00304 sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg); 00305 memp_free(MEMP_TCPIP_MSG_API, msg); 00306 break; 00307 00308 default: 00309 break; 00310 } 00311 } 00312 } 00313 00314 /** 00315 * Pass a received packet to tcpip_thread for input processing 00316 * 00317 * @param p the received packet, p->payload pointing to the Ethernet header or 00318 * to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag) 00319 * @param inp the network interface on which the packet was received 00320 */ 00321 err_t 00322 tcpip_input(struct pbuf *p, struct netif *inp) 00323 { 00324 struct tcpip_msg *msg; 00325 00326 if (mbox != SYS_MBOX_NULL) { 00327 msg = memp_malloc(MEMP_TCPIP_MSG_INPKT); 00328 if (msg == NULL) { 00329 return ERR_MEM; 00330 } 00331 00332 msg->type = TCPIP_MSG_INPKT; 00333 msg->msg.inp.p = p; 00334 msg->msg.inp.netif = inp; 00335 if (sys_mbox_trypost(mbox, msg) != ERR_OK) { 00336 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00337 return ERR_MEM; 00338 } 00339 return ERR_OK; 00340 } 00341 return ERR_VAL; 00342 } 00343 00344 /** 00345 * Call a specific function in the thread context of 00346 * tcpip_thread for easy access synchronization. 00347 * A function called in that way may access lwIP core code 00348 * without fearing concurrent access. 00349 * 00350 * @param f the function to call 00351 * @param ctx parameter passed to f 00352 * @param block 1 to block until the request is posted, 0 to non-blocking mode 00353 * @return ERR_OK if the function was called, another err_t if not 00354 */ 00355 err_t 00356 tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block) 00357 { 00358 struct tcpip_msg *msg; 00359 00360 if (mbox != SYS_MBOX_NULL) { 00361 msg = memp_malloc(MEMP_TCPIP_MSG_API); 00362 if (msg == NULL) { 00363 return ERR_MEM; 00364 } 00365 00366 msg->type = TCPIP_MSG_CALLBACK; 00367 msg->msg.cb.f = f; 00368 msg->msg.cb.ctx = ctx; 00369 if (block) { 00370 sys_mbox_post(mbox, msg); 00371 } else { 00372 if (sys_mbox_trypost(mbox, msg) != ERR_OK) { 00373 memp_free(MEMP_TCPIP_MSG_API, msg); 00374 return ERR_MEM; 00375 } 00376 } 00377 return ERR_OK; 00378 } 00379 return ERR_VAL; 00380 } 00381 00382 err_t 00383 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) 00384 { 00385 struct tcpip_msg *msg; 00386 00387 if (mbox != SYS_MBOX_NULL) { 00388 msg = memp_malloc(MEMP_TCPIP_MSG_API); 00389 if (msg == NULL) { 00390 return ERR_MEM; 00391 } 00392 00393 msg->type = TCPIP_MSG_TIMEOUT; 00394 msg->msg.tmo.msecs = msecs; 00395 msg->msg.tmo.h = h; 00396 msg->msg.tmo.arg = arg; 00397 sys_mbox_post(mbox, msg); 00398 return ERR_OK; 00399 } 00400 return ERR_VAL; 00401 } 00402 00403 #if LWIP_NETCONN 00404 /** 00405 * Call the lower part of a netconn_* function 00406 * This function is then running in the thread context 00407 * of tcpip_thread and has exclusive access to lwIP core code. 00408 * 00409 * @param apimsg a struct containing the function to call and its parameters 00410 * @return ERR_OK if the function was called, another err_t if not 00411 */ 00412 err_t 00413 tcpip_apimsg(struct api_msg *apimsg) 00414 { 00415 struct tcpip_msg msg; 00416 00417 if (mbox != SYS_MBOX_NULL) { 00418 msg.type = TCPIP_MSG_API; 00419 msg.msg.apimsg = apimsg; 00420 sys_mbox_post(mbox, &msg); 00421 sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); 00422 return ERR_OK; 00423 } 00424 return ERR_VAL; 00425 } 00426 00427 #if LWIP_TCPIP_CORE_LOCKING 00428 /** 00429 * Call the lower part of a netconn_* function 00430 * This function has exclusive access to lwIP core code by locking it 00431 * before the function is called. 00432 * 00433 * @param apimsg a struct containing the function to call and its parameters 00434 * @return ERR_OK (only for compatibility fo tcpip_apimsg()) 00435 */ 00436 err_t 00437 tcpip_apimsg_lock(struct api_msg *apimsg) 00438 { 00439 LOCK_TCPIP_CORE(); 00440 apimsg->function(&(apimsg->msg)); 00441 UNLOCK_TCPIP_CORE(); 00442 return ERR_OK; 00443 00444 } 00445 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00446 #endif /* LWIP_NETCONN */ 00447 00448 #if LWIP_NETIF_API 00449 #if !LWIP_TCPIP_CORE_LOCKING 00450 /** 00451 * Much like tcpip_apimsg, but calls the lower part of a netifapi_* 00452 * function. 00453 * 00454 * @param netifapimsg a struct containing the function to call and its parameters 00455 * @return error code given back by the function that was called 00456 */ 00457 err_t 00458 tcpip_netifapi(struct netifapi_msg* netifapimsg) 00459 { 00460 struct tcpip_msg msg; 00461 00462 if (mbox != SYS_MBOX_NULL) { 00463 netifapimsg->msg.sem = sys_sem_new(0); 00464 if (netifapimsg->msg.sem == SYS_SEM_NULL) { 00465 netifapimsg->msg.err = ERR_MEM; 00466 return netifapimsg->msg.err; 00467 } 00468 00469 msg.type = TCPIP_MSG_NETIFAPI; 00470 msg.msg.netifapimsg = netifapimsg; 00471 sys_mbox_post(mbox, &msg); 00472 sys_sem_wait(netifapimsg->msg.sem); 00473 sys_sem_free(netifapimsg->msg.sem); 00474 return netifapimsg->msg.err; 00475 } 00476 return ERR_VAL; 00477 } 00478 #else /* !LWIP_TCPIP_CORE_LOCKING */ 00479 /** 00480 * Call the lower part of a netifapi_* function 00481 * This function has exclusive access to lwIP core code by locking it 00482 * before the function is called. 00483 * 00484 * @param netifapimsg a struct containing the function to call and its parameters 00485 * @return ERR_OK (only for compatibility fo tcpip_netifapi()) 00486 */ 00487 err_t 00488 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) 00489 { 00490 LOCK_TCPIP_CORE(); 00491 netifapimsg->function(&(netifapimsg->msg)); 00492 UNLOCK_TCPIP_CORE(); 00493 return netifapimsg->msg.err; 00494 } 00495 #endif /* !LWIP_TCPIP_CORE_LOCKING */ 00496 #endif /* LWIP_NETIF_API */ 00497 00498 /** 00499 * Initialize this module: 00500 * - initialize all sub modules 00501 * - start the tcpip_thread 00502 * 00503 * @param initfunc a function to call when tcpip_thread is running and finished initializing 00504 * @param arg argument to pass to initfunc 00505 */ 00506 void 00507 tcpip_init(void (* initfunc)(void *), void *arg) 00508 { 00509 lwip_init(); 00510 00511 tcpip_init_done = initfunc; 00512 tcpip_init_done_arg = arg; 00513 mbox = sys_mbox_new(TCPIP_MBOX_SIZE); 00514 #if LWIP_TCPIP_CORE_LOCKING 00515 lock_tcpip_core = sys_sem_new(1); 00516 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00517 00518 sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); 00519 } 00520 00521 #endif /* !NO_SYS */
Generated on Tue Jul 12 2022 16:06:26 by 1.7.2