diff --git a/ChangeLog b/ChangeLog index 0c89ae7e9cb..f028a742597 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1167,4 +1167,10 @@ * arch/arm/src/lpc17xx/lpc17_serial.c - Improved logic to handle missed TX interrupts. * arch/arm/src/lpc17xx/lpc17_ssp.c - Fix a hard fault during SSP - initialization. \ No newline at end of file + initialization. + * configs/nucleus2g/src/up_led.c - Change how LEDs are controlled + so that they can be used both for NuttX instrumentation and + by application software. + * include/net/uip/igmp.h and uip-igmp.h - Add header files ini + preparation for NuttX IGMP support + * net/uip/uip_igmpinit.c, uip_igmpgroup.c - Add IGMP logic. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 9d5530b0244..6ca1dbb5452 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -8,7 +8,7 @@

NuttX RTOS

-

Last Updated: July 3, 2010

+

Last Updated: July 7, 2010

@@ -1843,6 +1843,12 @@ nuttx-5.8 2010-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> missed TX interrupts. * arch/arm/src/lpc17xx/lpc17_ssp.c - Fix a hard fault during SSP initialization. + * configs/nucleus2g/src/up_led.c - Change how LEDs are controlled + so that they can be used both for NuttX instrumentation and + by application software. + * include/net/uip/igmp.h and uip-igmp.h - Add header files ini + preparation for NuttX IGMP support + * net/uip/uip_igmpinit.c, uip_igmpgroup.c - Add IGMP logic. pascal-2.1 2010-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/include/net/uip/uip-arch.h b/include/net/uip/uip-arch.h index 3184ac0f7cd..939c60450d3 100644 --- a/include/net/uip/uip-arch.h +++ b/include/net/uip/uip-arch.h @@ -176,7 +176,7 @@ struct uip_driver_s /* IGMP group list */ #ifdef CONFIG_NET_IGMP - FAR struct igmp_group_s *grplist; + sq_queue_t grplist; #endif /* Driver callbacks */ diff --git a/include/net/uip/uip-igmp.h b/include/net/uip/uip-igmp.h index 56c6a17b300..4b7db8fc191 100755 --- a/include/net/uip/uip-igmp.h +++ b/include/net/uip/uip-igmp.h @@ -90,6 +90,20 @@ #define IGMP_DELAYING_MEMBER 1 #define IGMP_IDLE_MEMBER 2 +/* Group flags */ + +#define IGMP_PREALLOCATED 1 +#define IGMP_LASTREPORT 2 + +#define SET_PREALLOCATED(f) do { (f) |= IGMP_PREALLOCATED; } while (0) +#define SET_LASTREPORT(f) do { (f) |= IGMP_LASTREPORT; } while (0) + +#define CLR_PREALLOCATED(f) do { (f) &= ~IGMP_PREALLOCATED; } while (0) +#define CLR_LASTREPORT(f) do { (f) &= ~IGMP_LASTREPORT; } while (0) + +#define IS_PREALLOCATED(f) (((f) & IGMP_PREALLOCATED) != 0) +#define IS_LASTREPORT(f) (((f) & IGMP_LASTREPORT) != 0) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -174,7 +188,7 @@ struct igmp_group_s struct igmp_group_s *next; /* Implements a singly-linked list */ uip_ipaddr_t grpaddr; /* Group IP address */ WDOG_ID wdog; /* WDOG used to detect timeouts */ - bool lastrpt; /* Indicates the last to report */ + uint8_t flags; /* See IGMP_ flags definitions */ uint8_t state; /* State of the group */ uint8_t msgid; /* Pending message ID (if non-zero) */ }; diff --git a/net/uip/Make.defs b/net/uip/Make.defs index 31011ffa35c..4f94b4eab85 100644 --- a/net/uip/Make.defs +++ b/net/uip/Make.defs @@ -79,7 +79,7 @@ endif endif ifeq ($(CONFIG_NET_IGMP),y) -UIP_CSRCS += uip_igmpinit.c +UIP_CSRCS += uip_igmpinit.c uip_igmpgroup.c endif endif diff --git a/net/uip/uip_igmpgroup.c b/net/uip/uip_igmpgroup.c new file mode 100755 index 00000000000..295800941e0 --- /dev/null +++ b/net/uip/uip_igmpgroup.c @@ -0,0 +1,291 @@ +/**************************************************************************** + * net/uip/uip_igmpgroup.c + * IGMP group data structure management logic + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * The NuttX implementation of IGMP was inspired by the IGMP add-on for the + * lwIP TCP/IP stack by Steve Reynolds: + * + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "uip_internal.h" + +#ifdef CONFIG_NET_IGMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +# error "IGMP for IPv6 not supported" +#endif + +#ifndef CONFIG_PREALLOC_IGMPGROUPS +# define CONFIG_PREALLOC_IGMPGROUPS 4 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* malloc() cannot be called from an interrupt handler. To work around this, + * a small number of IGMP groups are preallocated just for use in interrupt + * handling logic. + */ + +static struct igmp_group_s g_preallocgrps[CONFIG_PREALLOC_IGMPGROUPS]; +static FAR sq_queue_t g_freelist; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_grpalloc + * + * Description: + * Allocate a new group from heap memory. + * + * Assumptions: + * Calls malloc and so cannot be called from an interrupt handler. + * + ****************************************************************************/ + +static inline FAR struct igmp_group_s *uip_grpheapalloc(void) +{ + return (FAR struct igmp_group_s *)zalloc(sizeof(struct igmp_group_s)); +} + +/**************************************************************************** + * Name: uip_grpprealloc + * + * Description: + * Allocate a new group from the pre-allocated groups. + * + * Assumptions: + * This function should only be called from an interrupt handler (or with + * interrupts disabled). + * + ****************************************************************************/ + +static inline FAR struct igmp_group_s *uip_grpprealloc(void) +{ + FAR struct igmp_group_s *group = (FAR struct igmp_group_s *)sq_remfirst(&g_freelist); + if (group) + { + memset(group, 0, sizeof(struct igmp_group_s)); + group->flags = IGMP_PREALLOCATED; + } + return group; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uip_grpinit + * + * Description: + * One-time initialization of group data. + * + * Assumptions: + * Called only during early boot phases (pre-multitasking). + * + ****************************************************************************/ + +void uip_grpinit(void) +{ + FAR struct igmp_group_s *group; + int i; + + for (i = 0; i < CONFIG_PREALLOC_IGMPGROUPS; i++) + { + group = &g_preallocgrps[i]; + sq_addfirst((FAR sq_entry_t *)group, &g_freelist); + } +} + +/**************************************************************************** + * Name: uip_grpalloc + * + * Description: + * Allocate a new group from heap memory. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +FAR struct igmp_group_s *uip_grpalloc(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *addr) +{ + FAR struct igmp_group_s *group; + irqstate_t flags; + + nllvdbg("addr: %08x dev: %p\n", *addr, dev); + if (up_interrupt_context()) + { + group = uip_grpheapalloc(); + } + else + { + group = uip_grpprealloc(); + } + + /* Check if we succesfully allocated a group structure */ + + if (group) + { + /* Initialize the non-zero elements of the group structure */ + + uip_ipaddr_copy(group->grpaddr, addr); + + /* Interrupts must be disabled in order to modify the group list */ + + flags = irqsave(); + + /* Add the group structure to the list in the device structure */ + + sq_addfirst((FAR sq_entry_t*)group, &dev->grplist); + irqrestore(flags); + } + return group; +} + +/**************************************************************************** + * Name: uip_grpfind + * + * Description: + * Find an existing group. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +FAR struct igmp_group_s *uip_grpfind(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *addr) +{ + FAR struct igmp_group_s *group; + irqstate_t flags; + + /* We must disable interrupts because we don't which context we were called + * from. + */ + + flags = irqsave(); + for (group = (FAR struct igmp_group_s *)dev->grplist.head; group; group = group->next) + { + if (uip_ipaddr_cmp(&group->grpaddr, addr)) + { + break; + } + } + irqrestore(flags); + return group; +} + +/**************************************************************************** + * Name: uip_grpallocfind + * + * Description: + * Find an existing group. If not found, create a new group for the + * address. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +FAR struct igmp_group_s *uip_grpallocfind(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *addr) +{ + FAR struct igmp_group_s *group = uip_grpfind(dev, addr); + if (!group) + { + group = uip_grpalloc(dev, addr); + } + return group; +} + +/**************************************************************************** + * Name: uip_grpfree + * + * Description: + * Release a previously allocated group. + * + * Assumptions: + * May be called from either user or interrupt level processing. + * + ****************************************************************************/ + +void uip_grpfree(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group) +{ + /* First, remove the group structure from the group list in the device + * structure + */ + + irqstate_t flags = irqsave(); + DEBUGASSERT(sq_rem((FAR sq_entry_t*)group, &dev->grplist) != NULL); + if (IS_PREALLOCATED(group->flags)) + { + sq_addlast((FAR sq_entry_t*)group, &g_freelist); + irqrestore(flags); + } + else + { + irqrestore(flags); + free(group); + } +} + +#endif /* CONFIG_NET_IGMP */ diff --git a/net/uip/uip_igmpinit.c b/net/uip/uip_igmpinit.c index 32d986835df..9dceb0134a7 100755 --- a/net/uip/uip_igmpinit.c +++ b/net/uip/uip_igmpinit.c @@ -68,6 +68,10 @@ uip_ipaddr_t g_allsystems; uip_ipaddr_t g_allrouters; +/**************************************************************************** + * Public Functions + ****************************************************************************/ + /**************************************************************************** * Name: uip_igmpinit * diff --git a/net/uip/uip_internal.h b/net/uip/uip_internal.h index af20911d320..8570fba5b49 100644 --- a/net/uip/uip_internal.h +++ b/net/uip/uip_internal.h @@ -223,6 +223,12 @@ EXTERN void uip_igmpinput(struct uip_driver_s *dev); EXTERN void uip_grpinit(void); EXTERN FAR struct igmp_group_s *uip_grpalloc(FAR struct uip_driver_s *dev, FAR uip_ipaddr_t *addr); +EXTERN FAR struct igmp_group_s *uip_grpfind(FAR struct uip_driver_s *dev, + FAR uip_ipaddr_t *addr); +EXTERN FAR struct igmp_group_s *uip_grpallocfind(FAR struct uip_driver_s *dev, + FAR uip_ipaddr_t *addr); +EXTERN void uip_grpfree(FAR struct uip_driver_s *dev, + FAR struct igmp_group_s *group); /* Defined in TBD */