UbixOS  2.0
tcpip.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
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.
15  *
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
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32 
33 #include <net/opt.h>
34 
35 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */
36 
37 #include <net/priv/tcpip_priv.h>
38 #include <net/sys.h>
39 #include <net/memp.h>
40 #include <net/mem.h>
41 #include <net/init.h>
42 #include <net/ip.h>
43 #include <net/pbuf.h>
44 #include <net/etharp.h>
45 #include <netif/ethernet.h>
46 
47 #define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
48 #define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
49 #define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
50 #define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
51 
52 /* global variables */
53 static tcpip_init_done_fn tcpip_init_done;
54 static void *tcpip_init_done_arg;
55 static sys_mbox_t mbox;
56 
57 #if LWIP_TCPIP_CORE_LOCKING
58 
59 sys_mutex_t lock_tcpip_core;
60 #endif /* LWIP_TCPIP_CORE_LOCKING */
61 
62 #if LWIP_TIMERS
63 /* wait for a message, timeouts are processed while waiting */
64 #define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
65 #else /* LWIP_TIMERS */
66 /* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
67 #define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
68 #endif /* LWIP_TIMERS */
69 
80 static void tcpip_thread(void *arg) {
81  struct tcpip_msg *msg;
83 
84  if (tcpip_init_done != NULL) {
85  tcpip_init_done(tcpip_init_done_arg);
86  }
87 
89  while (1) { /* MAIN Loop */
92  /* wait for a message, timeouts are processed while waiting */
93  TCPIP_MBOX_FETCH(&mbox, (void ** )&msg);
95  if (msg == NULL) {
96  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
97  LWIP_ASSERT("tcpip_thread: invalid message", 0);
98  continue;
99  }
100 //kprintf("MSG->TYPE: 0x%X]", msg->type);
101  switch (msg->type) {
102 #if !LWIP_TCPIP_CORE_LOCKING
103  case TCPIP_MSG_API:
104  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
105  msg->msg.api_msg.function(msg->msg.api_msg.msg);
106  break;
107  case TCPIP_MSG_API_CALL:
108  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
109  msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
110  sys_sem_signal(msg->msg.api_call.sem);
111  break;
112 #endif /* !LWIP_TCPIP_CORE_LOCKING */
113 
114 #if !LWIP_TCPIP_CORE_LOCKING_INPUT
115  case TCPIP_MSG_INPKT:
116  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
117  msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
118  memp_free(MEMP_TCPIP_MSG_INPKT, msg);
119  break;
120 #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
121 
122 #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
123  case TCPIP_MSG_TIMEOUT:
124  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
125  sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
126  memp_free(MEMP_TCPIP_MSG_API, msg);
127  break;
128  case TCPIP_MSG_UNTIMEOUT:
129  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
130  sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
131  memp_free(MEMP_TCPIP_MSG_API, msg);
132  break;
133 #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
134 
135  case TCPIP_MSG_CALLBACK:
136  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
137  msg->msg.cb.function(msg->msg.cb.ctx);
138  memp_free(MEMP_TCPIP_MSG_API, msg);
139  break;
140 
142  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
143  msg->msg.cb.function(msg->msg.cb.ctx);
144  break;
145 
146  default:
147  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
148  LWIP_ASSERT("tcpip_thread: invalid message", 0);
149  break;
150  }
151  }
152 }
153 
162 #if LWIP_TCPIP_CORE_LOCKING_INPUT
163  err_t ret;
164  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
165  LOCK_TCPIP_CORE();
166  ret = input_fn(p, inp);
168  return ret;
169 #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
170  struct tcpip_msg *msg;
171 
172  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
173 
174  msg = (struct tcpip_msg *) memp_malloc(MEMP_TCPIP_MSG_INPKT);
175  if (msg == NULL) {
176  return ERR_MEM;
177  }
178 
179  msg->type = TCPIP_MSG_INPKT;
180  msg->msg.inp.p = p;
181  msg->msg.inp.netif = inp;
182  msg->msg.inp.input_fn = input_fn;
183  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
184  kprintf("INPKT %i\n", __LINE__);
185  memp_free(MEMP_TCPIP_MSG_INPKT, msg);
186  kprintf("INPKT %i\n", __LINE__);
187  return ERR_MEM;
188  }
189  return ERR_OK;
190 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
191 }
192 
204 err_t tcpip_input(struct pbuf *p, struct netif *inp) {
205 #if LWIP_ETHERNET
206  //kprintf("tcpip_input0\n");
207  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
208  //kprintf("tcpip_input1\n");
209  return tcpip_inpkt(p, inp, ethernet_input);
210  }
211  else
212 #endif /* LWIP_ETHERNET */
213  //kprintf("tcpip_input2\n");
214  return tcpip_inpkt(p, inp, ip_input);
215  //kprintf("tcpip_input3\n");
216 }
217 
230  struct tcpip_msg *msg;
231 
232  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
233 
234  msg = (struct tcpip_msg *) memp_malloc(MEMP_TCPIP_MSG_API);
235  if (msg == NULL) {
236  return ERR_MEM;
237  }
238 
239  msg->type = TCPIP_MSG_CALLBACK;
240  msg->msg.cb.function = function;
241  msg->msg.cb.ctx = ctx;
242  if (block) {
243  sys_mbox_post(&mbox, msg);
244  }
245  else {
246  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
247  memp_free(MEMP_TCPIP_MSG_API, msg);
248  return ERR_MEM;
249  }
250  }
251  return ERR_OK;
252 }
253 
254 #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
255 
263 err_t
264 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
265 {
266  struct tcpip_msg *msg;
267 
268  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
269 
270  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
271  if (msg == NULL) {
272  return ERR_MEM;
273  }
274 
275  msg->type = TCPIP_MSG_TIMEOUT;
276  msg->msg.tmo.msecs = msecs;
277  msg->msg.tmo.h = h;
278  msg->msg.tmo.arg = arg;
279  sys_mbox_post(&mbox, msg);
280  return ERR_OK;
281 }
282 
290 err_t
291 tcpip_untimeout(sys_timeout_handler h, void *arg)
292 {
293  struct tcpip_msg *msg;
294 
295  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
296 
297  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
298  if (msg == NULL) {
299  return ERR_MEM;
300  }
301 
302  msg->type = TCPIP_MSG_UNTIMEOUT;
303  msg->msg.tmo.h = h;
304  msg->msg.tmo.arg = arg;
305  sys_mbox_post(&mbox, msg);
306  return ERR_OK;
307 }
308 #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
309 
323 #if LWIP_TCPIP_CORE_LOCKING
325  LOCK_TCPIP_CORE();
326  fn(apimsg);
328  return ERR_OK;
329 #else /* LWIP_TCPIP_CORE_LOCKING */
331 
332  LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
333  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
334 
337  TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
338  TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
342  return ERR_OK;
343 #endif /* LWIP_TCPIP_CORE_LOCKING */
344 }
345 
357 #if LWIP_TCPIP_CORE_LOCKING
358  err_t err;
359  LOCK_TCPIP_CORE();
360  err = fn(call);
362  return err;
363 #else /* LWIP_TCPIP_CORE_LOCKING */
365 
366 #if !LWIP_NETCONN_SEM_PER_THREAD
367  err_t err = sys_sem_new(&call->sem, 0);
368  if (err != ERR_OK) {
369  return err;
370  }
371 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
372 
373  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
374 
377  TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
378  TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
379 #if LWIP_NETCONN_SEM_PER_THREAD
380  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
381 #else /* LWIP_NETCONN_SEM_PER_THREAD */
382  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
383 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
385  sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
387 
388 #if !LWIP_NETCONN_SEM_PER_THREAD
389  sys_sem_free(&call->sem);
390 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
391 
392  return call->err;
393 #endif /* LWIP_TCPIP_CORE_LOCKING */
394 }
395 
404 struct tcpip_callback_msg*
406  struct tcpip_msg *msg = (struct tcpip_msg *) memp_malloc(MEMP_TCPIP_MSG_API);
407  if (msg == NULL) {
408  return NULL;
409  }
411  msg->msg.cb.function = function;
412  msg->msg.cb.ctx = ctx;
413  return (struct tcpip_callback_msg*) msg;
414 }
415 
421 void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) {
422  memp_free(MEMP_TCPIP_MSG_API, msg);
423 }
424 
432 err_t tcpip_trycallback(struct tcpip_callback_msg* msg) {
433  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
434  return sys_mbox_trypost(&mbox, msg);
435 }
436 
446 void tcpip_init(tcpip_init_done_fn initfunc, void *arg) {
447  lwip_init();
448 
449  tcpip_init_done = initfunc;
450  tcpip_init_done_arg = arg;
451  if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
452  LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
453  }
454 #if LWIP_TCPIP_CORE_LOCKING
455  if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
456  LWIP_ASSERT("failed to create lock_tcpip_core", 0);
457  }
458 #endif /* LWIP_TCPIP_CORE_LOCKING */
459 
461 }
462 
469 static void pbuf_free_int(void *p) {
470  struct pbuf *q = (struct pbuf *) p;
471  pbuf_free(q);
472 }
473 
481  return tcpip_callback_with_block(pbuf_free_int, p, 0);
482 }
483 
492  return tcpip_callback_with_block(mem_free, m, 0);
493 }
494 
495 #endif /* !NO_SYS */
tcpip_priv.h
tcpip_callback_with_block
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:229
TCPIP_MSG_VAR_DECLARE
#define TCPIP_MSG_VAR_DECLARE(name)
Definition: tcpip.c:48
sys.h
tcpip_msg::sem
sys_sem_t * sem
Definition: tcpip_priv.h:133
opt.h
LWIP_ASSERT
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
pbuf.h
sys_sem_new
err_t sys_sem_new(sys_sem_t **sem, u8_t count)
Definition: sys_arch.c:52
TCPIP_MSG_INPKT
Definition: tcpip_priv.h:114
sys_sem_free
void sys_sem_free(sys_sem_t **sem)
Definition: sys_arch.c:75
tcpip_api_call_data
Definition: tcpip_priv.h:97
sys_sem_valid
int sys_sem_valid(struct sys_sem **s)
Definition: sys_arch.c:131
sys_arch_sem_wait
uint32_t sys_arch_sem_wait(struct sys_sem **s, uint32_t timeout)
Definition: sys_arch.c:104
tcpip_api_call_data::err
err_t err
Definition: tcpip_priv.h:100
tcpip_init
void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
Definition: tcpip.c:446
NETIF_FLAG_ETHARP
#define NETIF_FLAG_ETHARP
Definition: netif.h:99
UNLOCK_TCPIP_CORE
#define UNLOCK_TCPIP_CORE()
Definition: tcpip.h:61
u32_t
uint32_t u32_t
Definition: arch.h:126
mem_free_callback
err_t mem_free_callback(void *m)
Definition: tcpip.c:491
pbuf_free
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:715
sys_thread_new
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition: sys_arch.c:378
sys_mbox_post
void sys_mbox_post(struct sys_mbox **mb, void *msg)
Definition: sys_arch.c:214
pbuf_free_callback
err_t pbuf_free_callback(struct pbuf *p)
Definition: tcpip.c:480
LWIP_TCPIP_THREAD_ALIVE
#define LWIP_TCPIP_THREAD_ALIVE()
Definition: lwipopts.h:249
memp_malloc
void * memp_malloc(memp_t type)
Definition: memp.c:385
netif_input_fn
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
Definition: netif.h:170
mem_free
void mem_free(void *mem)
Definition: mem.c:419
sys_sem
Definition: sem.h:36
memp_free
void memp_free(memp_t type, void *mem)
Definition: memp.c:469
tcpip_msg::msg
void * msg
Definition: tcpip_priv.h:128
tcpip_init_done_fn
void(* tcpip_init_done_fn)(void *arg)
Definition: tcpip.h:68
tcpip_api_call_data::sem
sys_sem_t sem
Definition: tcpip_priv.h:102
ERR_MEM
Definition: err.h:65
TCPIP_MSG_VAR_REF
#define TCPIP_MSG_VAR_REF(name)
Definition: tcpip.c:47
sys_sem_signal
void sys_sem_signal(struct sys_sem **s)
Definition: sys_arch.c:88
TCPIP_MBOX_FETCH
#define TCPIP_MBOX_FETCH(mbox, msg)
Definition: tcpip.c:67
u8_t
uint8_t u8_t
Definition: arch.h:122
TCPIP_MSG_VAR_ALLOC
#define TCPIP_MSG_VAR_ALLOC(name)
Definition: tcpip.c:49
tcpip_input
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition: tcpip.c:204
tcpip_msg::inp
struct tcpip_msg::@3::@6 inp
sys_mbox_valid_val
#define sys_mbox_valid_val(mbox)
Definition: sys.h:271
init.h
netif
Definition: netif.h:233
tcpip_msg::input_fn
netif_input_fn input_fn
Definition: tcpip_priv.h:138
TCPIP_DEBUG
#define TCPIP_DEBUG
Definition: lwipopts.h:482
TCPIP_THREAD_NAME
#define TCPIP_THREAD_NAME
Definition: lwipopts.h:241
LWIP_UNUSED_ARG
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:315
tcpip_inpkt
err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
Definition: tcpip.c:161
ethernet.h
sys_mutex_new
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.c:143
TCPIP_THREAD_PRIO
#define TCPIP_THREAD_PRIO
Definition: lwipopts.h:245
TCPIP_MSG_CALLBACK_STATIC
Definition: tcpip_priv.h:120
tcpip_msg
Definition: tcpip_priv.h:123
ERR_OK
Definition: err.h:63
tcpip_trycallback
err_t tcpip_trycallback(struct tcpip_callback_msg *msg)
Definition: tcpip.c:432
err_t
s8_t err_t
Definition: err.h:57
NETIF_FLAG_ETHERNET
#define NETIF_FLAG_ETHERNET
Definition: netif.h:103
ip.h
TCPIP_MSG_API
Definition: tcpip_priv.h:112
etharp.h
TCPIP_MBOX_SIZE
#define TCPIP_MBOX_SIZE
Definition: lwipopts.h:247
lwip_init
void lwip_init(void)
Definition: init.c:333
TCPIP_MSG_API_CALL
Definition: tcpip_priv.h:113
tcpip_msg::ctx
void * ctx
Definition: tcpip_priv.h:142
tcpip_callbackmsg_delete
void tcpip_callbackmsg_delete(struct tcpip_callback_msg *msg)
Definition: tcpip.c:421
TCPIP_THREAD_STACKSIZE
#define TCPIP_THREAD_STACKSIZE
Definition: lwipopts.h:243
tcpip_callback_fn
void(* tcpip_callback_fn)(void *ctx)
Definition: tcpip.h:70
sys_mbox_new
err_t sys_mbox_new(struct sys_mbox **mb, int size)
Definition: sys_arch.c:160
TCPIP_MSG_VAR_FREE
#define TCPIP_MSG_VAR_FREE(name)
Definition: tcpip.c:50
memp.h
tcpip_msg::p
struct pbuf * p
Definition: tcpip_priv.h:136
mem.h
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
sys_mbox_trypost
err_t sys_mbox_trypost(struct sys_mbox **mb, void *msg)
Definition: sys_arch.c:250
pbuf
Definition: pbuf.h:142
sys_mutex
Definition: sys_arch.h:16
LWIP_DEBUGF
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:164
LOCK_TCPIP_CORE
#define LOCK_TCPIP_CORE()
Definition: tcpip.h:60
TCPIP_MSG_CALLBACK
Definition: tcpip_priv.h:119
tcpip_send_msg_wait_sem
err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
Definition: tcpip.c:322
tcpip_msg::arg
struct tcpip_api_call_data * arg
Definition: tcpip_priv.h:132
tcpip_callbackmsg_new
struct tcpip_callback_msg * tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
Definition: tcpip.c:405
tcpip_api_call
err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
Definition: tcpip.c:356
sys_mbox
Definition: sys_arch.h:22
tcpip_api_call_fn
err_t(* tcpip_api_call_fn)(struct tcpip_api_call_data *call)
Definition: tcpip_priv.h:108
NULL
#define NULL
Definition: fat_string.h:17