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