Deprecated fork of old network stack source from github. Please use official library instead: https://mbed.org/users/mbed_official/code/EthernetInterface/
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 #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 case TCPIP_MSG_CALLBACK: 00121 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); 00122 msg->msg.cb.function(msg->msg.cb.ctx); 00123 memp_free(MEMP_TCPIP_MSG_API, msg); 00124 break; 00125 00126 #if LWIP_TCPIP_TIMEOUT 00127 case TCPIP_MSG_TIMEOUT: 00128 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); 00129 sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); 00130 memp_free(MEMP_TCPIP_MSG_API, msg); 00131 break; 00132 case TCPIP_MSG_UNTIMEOUT: 00133 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); 00134 sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); 00135 memp_free(MEMP_TCPIP_MSG_API, msg); 00136 break; 00137 #endif /* LWIP_TCPIP_TIMEOUT */ 00138 00139 default: 00140 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); 00141 LWIP_ASSERT("tcpip_thread: invalid message", 0); 00142 break; 00143 } 00144 } 00145 } 00146 00147 /** 00148 * Pass a received packet to tcpip_thread for input processing 00149 * 00150 * @param p the received packet, p->payload pointing to the Ethernet header or 00151 * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or 00152 * NETIF_FLAG_ETHERNET flags) 00153 * @param inp the network interface on which the packet was received 00154 */ 00155 err_t 00156 tcpip_input(struct pbuf *p, struct netif *inp) 00157 { 00158 #if LWIP_TCPIP_CORE_LOCKING_INPUT 00159 err_t ret; 00160 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); 00161 LOCK_TCPIP_CORE(); 00162 #if LWIP_ETHERNET 00163 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 00164 ret = ethernet_input(p, inp); 00165 } else 00166 #endif /* LWIP_ETHERNET */ 00167 { 00168 ret = ip_input(p, inp); 00169 } 00170 UNLOCK_TCPIP_CORE(); 00171 return ret; 00172 #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ 00173 struct tcpip_msg *msg; 00174 00175 if (sys_mbox_valid(&mbox)) { 00176 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); 00177 if (msg == NULL) { 00178 return ERR_MEM; 00179 } 00180 00181 msg->type = TCPIP_MSG_INPKT; 00182 msg->msg.inp.p = p; 00183 msg->msg.inp.netif = inp; 00184 if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { 00185 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00186 return ERR_MEM; 00187 } 00188 return ERR_OK; 00189 } 00190 return ERR_VAL; 00191 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ 00192 } 00193 00194 /** 00195 * Call a specific function in the thread context of 00196 * tcpip_thread for easy access synchronization. 00197 * A function called in that way may access lwIP core code 00198 * without fearing concurrent access. 00199 * 00200 * @param f the function to call 00201 * @param ctx parameter passed to f 00202 * @param block 1 to block until the request is posted, 0 to non-blocking mode 00203 * @return ERR_OK if the function was called, another err_t if not 00204 */ 00205 err_t 00206 tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) 00207 { 00208 struct tcpip_msg *msg; 00209 00210 if (sys_mbox_valid(&mbox)) { 00211 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00212 if (msg == NULL) { 00213 return ERR_MEM; 00214 } 00215 00216 msg->type = TCPIP_MSG_CALLBACK; 00217 msg->msg.cb.function = function; 00218 msg->msg.cb.ctx = ctx; 00219 if (block) { 00220 sys_mbox_post(&mbox, msg); 00221 } else { 00222 if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { 00223 memp_free(MEMP_TCPIP_MSG_API, msg); 00224 return ERR_MEM; 00225 } 00226 } 00227 return ERR_OK; 00228 } 00229 return ERR_VAL; 00230 } 00231 00232 #if LWIP_TCPIP_TIMEOUT 00233 /** 00234 * call sys_timeout in tcpip_thread 00235 * 00236 * @param msec time in milliseconds for timeout 00237 * @param h function to be called on timeout 00238 * @param arg argument to pass to timeout function h 00239 * @return ERR_MEM on memory error, ERR_OK otherwise 00240 */ 00241 err_t 00242 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) 00243 { 00244 struct tcpip_msg *msg; 00245 00246 if (sys_mbox_valid(&mbox)) { 00247 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00248 if (msg == NULL) { 00249 return ERR_MEM; 00250 } 00251 00252 msg->type = TCPIP_MSG_TIMEOUT; 00253 msg->msg.tmo.msecs = msecs; 00254 msg->msg.tmo.h = h; 00255 msg->msg.tmo.arg = arg; 00256 sys_mbox_post(&mbox, msg); 00257 return ERR_OK; 00258 } 00259 return ERR_VAL; 00260 } 00261 00262 /** 00263 * call sys_untimeout in tcpip_thread 00264 * 00265 * @param msec time in milliseconds for timeout 00266 * @param h function to be called on timeout 00267 * @param arg argument to pass to timeout function h 00268 * @return ERR_MEM on memory error, ERR_OK otherwise 00269 */ 00270 err_t 00271 tcpip_untimeout(sys_timeout_handler h, void *arg) 00272 { 00273 struct tcpip_msg *msg; 00274 00275 if (sys_mbox_valid(&mbox)) { 00276 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); 00277 if (msg == NULL) { 00278 return ERR_MEM; 00279 } 00280 00281 msg->type = TCPIP_MSG_UNTIMEOUT; 00282 msg->msg.tmo.h = h; 00283 msg->msg.tmo.arg = arg; 00284 sys_mbox_post(&mbox, msg); 00285 return ERR_OK; 00286 } 00287 return ERR_VAL; 00288 } 00289 #endif /* LWIP_TCPIP_TIMEOUT */ 00290 00291 #if LWIP_NETCONN 00292 /** 00293 * Call the lower part of a netconn_* function 00294 * This function is then running in the thread context 00295 * of tcpip_thread and has exclusive access to lwIP core code. 00296 * 00297 * @param apimsg a struct containing the function to call and its parameters 00298 * @return ERR_OK if the function was called, another err_t if not 00299 */ 00300 err_t 00301 tcpip_apimsg(struct api_msg *apimsg) 00302 { 00303 struct tcpip_msg msg; 00304 #ifdef LWIP_DEBUG 00305 /* catch functions that don't set err */ 00306 apimsg->msg.err = ERR_VAL; 00307 #endif 00308 00309 if (sys_mbox_valid(&mbox)) { 00310 msg.type = TCPIP_MSG_API; 00311 msg.msg.apimsg = apimsg; 00312 sys_mbox_post(&mbox, &msg); 00313 sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); 00314 return apimsg->msg.err; 00315 } 00316 return ERR_VAL; 00317 } 00318 00319 #if LWIP_TCPIP_CORE_LOCKING 00320 /** 00321 * Call the lower part of a netconn_* function 00322 * This function has exclusive access to lwIP core code by locking it 00323 * before the function is called. 00324 * 00325 * @param apimsg a struct containing the function to call and its parameters 00326 * @return ERR_OK (only for compatibility fo tcpip_apimsg()) 00327 */ 00328 err_t 00329 tcpip_apimsg_lock(struct api_msg *apimsg) 00330 { 00331 #ifdef LWIP_DEBUG 00332 /* catch functions that don't set err */ 00333 apimsg->msg.err = ERR_VAL; 00334 #endif 00335 00336 LOCK_TCPIP_CORE(); 00337 apimsg->function(&(apimsg->msg)); 00338 UNLOCK_TCPIP_CORE(); 00339 return apimsg->msg.err; 00340 00341 } 00342 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00343 #endif /* LWIP_NETCONN */ 00344 00345 #if LWIP_NETIF_API 00346 #if !LWIP_TCPIP_CORE_LOCKING 00347 /** 00348 * Much like tcpip_apimsg, but calls the lower part of a netifapi_* 00349 * function. 00350 * 00351 * @param netifapimsg a struct containing the function to call and its parameters 00352 * @return error code given back by the function that was called 00353 */ 00354 err_t 00355 tcpip_netifapi(struct netifapi_msg* netifapimsg) 00356 { 00357 struct tcpip_msg msg; 00358 00359 if (sys_mbox_valid(&mbox)) { 00360 err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); 00361 if (err != ERR_OK) { 00362 netifapimsg->msg.err = err; 00363 return err; 00364 } 00365 00366 msg.type = TCPIP_MSG_NETIFAPI; 00367 msg.msg.netifapimsg = netifapimsg; 00368 sys_mbox_post(&mbox, &msg); 00369 sys_sem_wait(&netifapimsg->msg.sem); 00370 sys_sem_free(&netifapimsg->msg.sem); 00371 return netifapimsg->msg.err; 00372 } 00373 return ERR_VAL; 00374 } 00375 #else /* !LWIP_TCPIP_CORE_LOCKING */ 00376 /** 00377 * Call the lower part of a netifapi_* function 00378 * This function has exclusive access to lwIP core code by locking it 00379 * before the function is called. 00380 * 00381 * @param netifapimsg a struct containing the function to call and its parameters 00382 * @return ERR_OK (only for compatibility fo tcpip_netifapi()) 00383 */ 00384 err_t 00385 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) 00386 { 00387 LOCK_TCPIP_CORE(); 00388 netifapimsg->function(&(netifapimsg->msg)); 00389 UNLOCK_TCPIP_CORE(); 00390 return netifapimsg->msg.err; 00391 } 00392 #endif /* !LWIP_TCPIP_CORE_LOCKING */ 00393 #endif /* LWIP_NETIF_API */ 00394 00395 /** 00396 * Initialize this module: 00397 * - initialize all sub modules 00398 * - start the tcpip_thread 00399 * 00400 * @param initfunc a function to call when tcpip_thread is running and finished initializing 00401 * @param arg argument to pass to initfunc 00402 */ 00403 void 00404 tcpip_init(tcpip_init_done_fn initfunc, void *arg) 00405 { 00406 lwip_init(); 00407 00408 tcpip_init_done = initfunc; 00409 tcpip_init_done_arg = arg; 00410 if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { 00411 LWIP_ASSERT("failed to create tcpip_thread mbox", 0); 00412 } 00413 #if LWIP_TCPIP_CORE_LOCKING 00414 if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { 00415 LWIP_ASSERT("failed to create lock_tcpip_core", 0); 00416 } 00417 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00418 00419 sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); 00420 } 00421 00422 /** 00423 * Simple callback function used with tcpip_callback to free a pbuf 00424 * (pbuf_free has a wrong signature for tcpip_callback) 00425 * 00426 * @param p The pbuf (chain) to be dereferenced. 00427 */ 00428 static void 00429 pbuf_free_int(void *p) 00430 { 00431 struct pbuf *q = (struct pbuf *)p; 00432 pbuf_free(q); 00433 } 00434 00435 /** 00436 * A simple wrapper function that allows you to free a pbuf from interrupt context. 00437 * 00438 * @param p The pbuf (chain) to be dereferenced. 00439 * @return ERR_OK if callback could be enqueued, an err_t if not 00440 */ 00441 err_t 00442 pbuf_free_callback(struct pbuf *p) 00443 { 00444 return tcpip_callback_with_block(pbuf_free_int, p, 0); 00445 } 00446 00447 /** 00448 * A simple wrapper function that allows you to free heap memory from 00449 * interrupt context. 00450 * 00451 * @param m the heap memory to free 00452 * @return ERR_OK if callback could be enqueued, an err_t if not 00453 */ 00454 err_t 00455 mem_free_callback(void *m) 00456 { 00457 return tcpip_callback_with_block(mem_free, m, 0); 00458 } 00459 00460 #endif /* !NO_SYS */
Generated on Tue Jul 12 2022 23:10:20 by 1.7.2