lwip-1.4.1 (partial)
Embed:
(wiki syntax)
Show/hide line numbers
tcpip.c
Go to the documentation of this file.
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/mem.h" 00046 #include "lwip/pbuf.h" 00047 #include "lwip/tcpip.h" 00048 #include "lwip/init.h" 00049 #include "netif/etharp.h" 00050 #include "netif/ppp_oe.h" 00051 00052 /* global variables */ 00053 static tcpip_init_done_fn tcpip_init_done; 00054 static void *tcpip_init_done_arg; 00055 static sys_mbox_t mbox; 00056 00057 #if LWIP_TCPIP_CORE_LOCKING 00058 /** The global semaphore to lock the stack. */ 00059 sys_mutex_t lock_tcpip_core; 00060 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00061 00062 00063 /** 00064 * The main lwIP thread. This thread has exclusive access to lwIP core functions 00065 * (unless access to them is not locked). Other threads communicate with this 00066 * thread using message boxes. 00067 * 00068 * It also starts all the timers to make sure they are running in the right 00069 * thread context. 00070 * 00071 * @param arg unused argument 00072 */ 00073 static void 00074 tcpip_thread(void *arg) 00075 { 00076 struct tcpip_msg *msg; 00077 LWIP_UNUSED_ARG(arg); 00078 00079 if (tcpip_init_done != NULL) { 00080 tcpip_init_done(tcpip_init_done_arg); 00081 } 00082 00083 LOCK_TCPIP_CORE(); 00084 while (1) { /* MAIN Loop */ 00085 UNLOCK_TCPIP_CORE(); 00086 LWIP_TCPIP_THREAD_ALIVE(); 00087 /* wait for a message, timeouts are processed while waiting */ 00088 sys_timeouts_mbox_fetch(&mbox, (void **)&msg); 00089 LOCK_TCPIP_CORE(); 00090 switch (msg->type) { 00091 #if LWIP_NETCONN 00092 case TCPIP_MSG_API: 00093 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); 00094 msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); 00095 break; 00096 #endif /* LWIP_NETCONN */ 00097 00098 #if !LWIP_TCPIP_CORE_LOCKING_INPUT 00099 case TCPIP_MSG_INPKT: 00100 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); 00101 #if LWIP_ETHERNET 00102 if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 00103 ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); 00104 } else 00105 #endif /* LWIP_ETHERNET */ 00106 { 00107 ip_input(msg->msg.inp.p, msg->msg.inp.netif); 00108 } 00109 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00110 break; 00111 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ 00112 00113 #if LWIP_NETIF_API 00114 case TCPIP_MSG_NETIFAPI: 00115 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); 00116 msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); 00117 break; 00118 #endif /* LWIP_NETIF_API */ 00119 00120 #if LWIP_TCPIP_TIMEOUT 00121 case TCPIP_MSG_TIMEOUT: 00122 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); 00123 sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); 00124 memp_free(MEMP_TCPIP_MSG_API, msg); 00125 break; 00126 case TCPIP_MSG_UNTIMEOUT: 00127 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); 00128 sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); 00129 memp_free(MEMP_TCPIP_MSG_API, msg); 00130 break; 00131 #endif /* LWIP_TCPIP_TIMEOUT */ 00132 00133 case TCPIP_MSG_CALLBACK: 00134 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); 00135 msg->msg.cb.function(msg->msg.cb.ctx); 00136 memp_free(MEMP_TCPIP_MSG_API, msg); 00137 break; 00138 00139 case TCPIP_MSG_CALLBACK_STATIC: 00140 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); 00141 msg->msg.cb.function(msg->msg.cb.ctx); 00142 break; 00143 00144 default: 00145 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); 00146 LWIP_ASSERT("tcpip_thread: invalid message", 0); 00147 break; 00148 } 00149 } 00150 } 00151 00152 /** 00153 * Pass a received packet to tcpip_thread for input processing 00154 * 00155 * @param p the received packet, p->payload pointing to the Ethernet header or 00156 * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or 00157 * NETIF_FLAG_ETHERNET flags) 00158 * @param inp the network interface on which the packet was received 00159 */ 00160 err_t 00161 tcpip_input(struct pbuf *p, struct netif *inp) 00162 { 00163 #if LWIP_TCPIP_CORE_LOCKING_INPUT 00164 err_t ret; 00165 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); 00166 LOCK_TCPIP_CORE(); 00167 #if LWIP_ETHERNET 00168 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 00169 ret = ethernet_input(p, inp); 00170 } else 00171 #endif /* LWIP_ETHERNET */ 00172 { 00173 ret = ip_input(p, inp); 00174 } 00175 UNLOCK_TCPIP_CORE(); 00176 return ret; 00177 #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ 00178 struct tcpip_msg *msg; 00179 00180 if (!sys_mbox_valid(&mbox)) { 00181 return ERR_VAL; 00182 } 00183 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); 00184 if (msg == NULL) { 00185 return ERR_MEM; 00186 } 00187 00188 msg->type = TCPIP_MSG_INPKT; 00189 msg->msg.inp.p = p; 00190 msg->msg.inp.netif = inp; 00191 if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { 00192 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00193 return ERR_MEM; 00194 } 00195 return ERR_OK; 00196 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ 00197 } 00198 00199 /** 00200 * Call a specific function in the thread context of 00201 * tcpip_thread for easy access synchronization. 00202 * A function called in that way may access lwIP core code 00203 * without fearing concurrent access. 00204 * 00205 * @param f the function to call 00206 * @param ctx parameter passed to f 00207 * @param block 1 to block until the request is posted, 0 to non-blocking mode 00208 * @return ERR_OK if the function was called, another err_t if not 00209 */ 00210 err_t 00211 tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) 00212 { 00213 struct tcpip_msg *msg; 00214 00215 if (sys_mbox_valid(&mbox)) { 00216 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00217 if (msg == NULL) { 00218 return ERR_MEM; 00219 } 00220 00221 msg->type = TCPIP_MSG_CALLBACK; 00222 msg->msg.cb.function = function; 00223 msg->msg.cb.ctx = ctx; 00224 if (block) { 00225 sys_mbox_post(&mbox, msg); 00226 } else { 00227 if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { 00228 memp_free(MEMP_TCPIP_MSG_API, msg); 00229 return ERR_MEM; 00230 } 00231 } 00232 return ERR_OK; 00233 } 00234 return ERR_VAL; 00235 } 00236 00237 #if LWIP_TCPIP_TIMEOUT 00238 /** 00239 * call sys_timeout in tcpip_thread 00240 * 00241 * @param msec time in milliseconds for timeout 00242 * @param h function to be called on timeout 00243 * @param arg argument to pass to timeout function h 00244 * @return ERR_MEM on memory error, ERR_OK otherwise 00245 */ 00246 err_t 00247 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) 00248 { 00249 struct tcpip_msg *msg; 00250 00251 if (sys_mbox_valid(&mbox)) { 00252 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00253 if (msg == NULL) { 00254 return ERR_MEM; 00255 } 00256 00257 msg->type = TCPIP_MSG_TIMEOUT; 00258 msg->msg.tmo.msecs = msecs; 00259 msg->msg.tmo.h = h; 00260 msg->msg.tmo.arg = arg; 00261 sys_mbox_post(&mbox, msg); 00262 return ERR_OK; 00263 } 00264 return ERR_VAL; 00265 } 00266 00267 /** 00268 * call sys_untimeout in tcpip_thread 00269 * 00270 * @param msec time in milliseconds for timeout 00271 * @param h function to be called on timeout 00272 * @param arg argument to pass to timeout function h 00273 * @return ERR_MEM on memory error, ERR_OK otherwise 00274 */ 00275 err_t 00276 tcpip_untimeout(sys_timeout_handler h, void *arg) 00277 { 00278 struct tcpip_msg *msg; 00279 00280 if (sys_mbox_valid(&mbox)) { 00281 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00282 if (msg == NULL) { 00283 return ERR_MEM; 00284 } 00285 00286 msg->type = TCPIP_MSG_UNTIMEOUT; 00287 msg->msg.tmo.h = h; 00288 msg->msg.tmo.arg = arg; 00289 sys_mbox_post(&mbox, msg); 00290 return ERR_OK; 00291 } 00292 return ERR_VAL; 00293 } 00294 #endif /* LWIP_TCPIP_TIMEOUT */ 00295 00296 #if LWIP_NETCONN 00297 /** 00298 * Call the lower part of a netconn_* function 00299 * This function is then running in the thread context 00300 * of tcpip_thread and has exclusive access to lwIP core code. 00301 * 00302 * @param apimsg a struct containing the function to call and its parameters 00303 * @return ERR_OK if the function was called, another err_t if not 00304 */ 00305 err_t 00306 tcpip_apimsg(struct api_msg *apimsg) 00307 { 00308 struct tcpip_msg msg; 00309 #ifdef LWIP_DEBUG 00310 /* catch functions that don't set err */ 00311 apimsg->msg.err = ERR_VAL; 00312 #endif 00313 00314 if (sys_mbox_valid(&mbox)) { 00315 msg.type = TCPIP_MSG_API; 00316 msg.msg.apimsg = apimsg; 00317 sys_mbox_post(&mbox, &msg); 00318 sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); 00319 return apimsg->msg.err; 00320 } 00321 return ERR_VAL; 00322 } 00323 00324 #if LWIP_TCPIP_CORE_LOCKING 00325 /** 00326 * Call the lower part of a netconn_* function 00327 * This function has exclusive access to lwIP core code by locking it 00328 * before the function is called. 00329 * 00330 * @param apimsg a struct containing the function to call and its parameters 00331 * @return ERR_OK (only for compatibility fo tcpip_apimsg()) 00332 */ 00333 err_t 00334 tcpip_apimsg_lock(struct api_msg *apimsg) 00335 { 00336 #ifdef LWIP_DEBUG 00337 /* catch functions that don't set err */ 00338 apimsg->msg.err = ERR_VAL; 00339 #endif 00340 00341 LOCK_TCPIP_CORE(); 00342 apimsg->function(&(apimsg->msg)); 00343 UNLOCK_TCPIP_CORE(); 00344 return apimsg->msg.err; 00345 00346 } 00347 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00348 #endif /* LWIP_NETCONN */ 00349 00350 #if LWIP_NETIF_API 00351 #if !LWIP_TCPIP_CORE_LOCKING 00352 /** 00353 * Much like tcpip_apimsg, but calls the lower part of a netifapi_* 00354 * function. 00355 * 00356 * @param netifapimsg a struct containing the function to call and its parameters 00357 * @return error code given back by the function that was called 00358 */ 00359 err_t 00360 tcpip_netifapi(struct netifapi_msg* netifapimsg) 00361 { 00362 struct tcpip_msg msg; 00363 00364 if (sys_mbox_valid(&mbox)) { 00365 err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); 00366 if (err != ERR_OK) { 00367 netifapimsg->msg.err = err; 00368 return err; 00369 } 00370 00371 msg.type = TCPIP_MSG_NETIFAPI; 00372 msg.msg.netifapimsg = netifapimsg; 00373 sys_mbox_post(&mbox, &msg); 00374 sys_sem_wait(&netifapimsg->msg.sem); 00375 sys_sem_free(&netifapimsg->msg.sem); 00376 return netifapimsg->msg.err; 00377 } 00378 return ERR_VAL; 00379 } 00380 #else /* !LWIP_TCPIP_CORE_LOCKING */ 00381 /** 00382 * Call the lower part of a netifapi_* function 00383 * This function has exclusive access to lwIP core code by locking it 00384 * before the function is called. 00385 * 00386 * @param netifapimsg a struct containing the function to call and its parameters 00387 * @return ERR_OK (only for compatibility fo tcpip_netifapi()) 00388 */ 00389 err_t 00390 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) 00391 { 00392 LOCK_TCPIP_CORE(); 00393 netifapimsg->function(&(netifapimsg->msg)); 00394 UNLOCK_TCPIP_CORE(); 00395 return netifapimsg->msg.err; 00396 } 00397 #endif /* !LWIP_TCPIP_CORE_LOCKING */ 00398 #endif /* LWIP_NETIF_API */ 00399 00400 /** 00401 * Allocate a structure for a static callback message and initialize it. 00402 * This is intended to be used to send "static" messages from interrupt context. 00403 * 00404 * @param function the function to call 00405 * @param ctx parameter passed to function 00406 * @return a struct pointer to pass to tcpip_trycallback(). 00407 */ 00408 struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) 00409 { 00410 struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00411 if (msg == NULL) { 00412 return NULL; 00413 } 00414 msg->type = TCPIP_MSG_CALLBACK_STATIC; 00415 msg->msg.cb.function = function; 00416 msg->msg.cb.ctx = ctx; 00417 return (struct tcpip_callback_msg*)msg; 00418 } 00419 00420 /** 00421 * Free a callback message allocated by tcpip_callbackmsg_new(). 00422 * 00423 * @param msg the message to free 00424 */ 00425 void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) 00426 { 00427 memp_free(MEMP_TCPIP_MSG_API, msg); 00428 } 00429 00430 /** 00431 * Try to post a callback-message to the tcpip_thread mbox 00432 * This is intended to be used to send "static" messages from interrupt context. 00433 * 00434 * @param msg pointer to the message to post 00435 * @return sys_mbox_trypost() return code 00436 */ 00437 err_t 00438 tcpip_trycallback(struct tcpip_callback_msg* msg) 00439 { 00440 if (!sys_mbox_valid(&mbox)) { 00441 return ERR_VAL; 00442 } 00443 return sys_mbox_trypost(&mbox, msg); 00444 } 00445 00446 /** 00447 * Initialize this module: 00448 * - initialize all sub modules 00449 * - start the tcpip_thread 00450 * 00451 * @param initfunc a function to call when tcpip_thread is running and finished initializing 00452 * @param arg argument to pass to initfunc 00453 */ 00454 void 00455 tcpip_init(tcpip_init_done_fn initfunc, void *arg) 00456 { 00457 lwip_init(); 00458 00459 tcpip_init_done = initfunc; 00460 tcpip_init_done_arg = arg; 00461 if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { 00462 LWIP_ASSERT("failed to create tcpip_thread mbox", 0); 00463 } 00464 #if LWIP_TCPIP_CORE_LOCKING 00465 if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { 00466 LWIP_ASSERT("failed to create lock_tcpip_core", 0); 00467 } 00468 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00469 00470 sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); 00471 } 00472 00473 /** 00474 * Simple callback function used with tcpip_callback to free a pbuf 00475 * (pbuf_free has a wrong signature for tcpip_callback) 00476 * 00477 * @param p The pbuf (chain) to be dereferenced. 00478 */ 00479 static void 00480 pbuf_free_int(void *p) 00481 { 00482 struct pbuf *q = (struct pbuf *)p; 00483 pbuf_free(q); 00484 } 00485 00486 /** 00487 * A simple wrapper function that allows you to free a pbuf from interrupt context. 00488 * 00489 * @param p The pbuf (chain) to be dereferenced. 00490 * @return ERR_OK if callback could be enqueued, an err_t if not 00491 */ 00492 err_t 00493 pbuf_free_callback(struct pbuf *p) 00494 { 00495 return tcpip_callback_with_block(pbuf_free_int, p, 0); 00496 } 00497 00498 /** 00499 * A simple wrapper function that allows you to free heap memory from 00500 * interrupt context. 00501 * 00502 * @param m the heap memory to free 00503 * @return ERR_OK if callback could be enqueued, an err_t if not 00504 */ 00505 err_t 00506 mem_free_callback(void *m) 00507 { 00508 return tcpip_callback_with_block(mem_free, m, 0); 00509 } 00510 00511 #endif /* !NO_SYS */
Generated on Wed Jul 13 2022 09:48:38 by 1.7.2