Merge remote-tracking branch 'origin/master' into ieee802154
This commit is contained in:
commit
94730f69d1
18 changed files with 882 additions and 233 deletions
|
|
@ -553,7 +553,7 @@ static inline int efm32_i2c_sem_waitdone(FAR struct efm32_i2c_priv_s *priv)
|
|||
|
||||
#ifdef CONFIG_EFM32_I2C_DYNTIMEO
|
||||
abstime.tv_nsec += 1000 * efm32_i2c_tousecs(priv->msgc, priv->msgv);
|
||||
if (abstime.tv_nsec > 1000 * 1000 * 1000)
|
||||
if (abstime.tv_nsec >= 1000 * 1000 * 1000)
|
||||
{
|
||||
abstime.tv_sec++;
|
||||
abstime.tv_nsec -= 1000 * 1000 * 1000;
|
||||
|
|
@ -561,7 +561,7 @@ static inline int efm32_i2c_sem_waitdone(FAR struct efm32_i2c_priv_s *priv)
|
|||
|
||||
#elif CONFIG_EFM32_I2CTIMEOMS > 0
|
||||
abstime.tv_nsec += CONFIG_EFM32_I2CTIMEOMS * 1000 * 1000;
|
||||
if (abstime.tv_nsec > 1000 * 1000 * 1000)
|
||||
if (abstime.tv_nsec >= 1000 * 1000 * 1000)
|
||||
{
|
||||
abstime.tv_sec++;
|
||||
abstime.tv_nsec -= 1000 * 1000 * 1000;
|
||||
|
|
|
|||
|
|
@ -744,7 +744,7 @@ CONFIG_ARCH_HAVE_SPI_BITORDER=y
|
|||
# CONFIG_SENSORS is not set
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_SERIAL_REMOVABLE=y
|
||||
CONFIG_SERIAL_CONSOLE=y
|
||||
# CONFIG_SERIAL_CONSOLE is not set
|
||||
# CONFIG_16550_UART is not set
|
||||
# CONFIG_UART_SERIALDRIVER is not set
|
||||
# CONFIG_UART0_SERIALDRIVER is not set
|
||||
|
|
@ -774,9 +774,9 @@ CONFIG_STANDARD_SERIAL=y
|
|||
# CONFIG_SERIAL_OFLOWCONTROL is not set
|
||||
# CONFIG_SERIAL_DMA is not set
|
||||
CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
|
||||
CONFIG_USART1_SERIAL_CONSOLE=y
|
||||
# CONFIG_USART1_SERIAL_CONSOLE is not set
|
||||
# CONFIG_OTHER_SERIAL_CONSOLE is not set
|
||||
# CONFIG_NO_SERIAL_CONSOLE is not set
|
||||
CONFIG_NO_SERIAL_CONSOLE=y
|
||||
|
||||
#
|
||||
# USART1 Configuration
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
#define SIXLOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */
|
||||
#define SIXLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */
|
||||
#define SIXLOWPAN_DISPATCH_FRAG_MASK 0xf1 /* 11111000 */
|
||||
#define SIXLOWPAN_DISPATCH_FRAG_MASK 0xf8 /* 11111000 */
|
||||
|
||||
/* HC1 encoding */
|
||||
|
||||
|
|
@ -398,6 +398,12 @@ struct ieee802154_driver_s
|
|||
|
||||
uint16_t i_reasstag;
|
||||
|
||||
/* i_boffset. Offset to the beginning of data in d_buf. As each fragment
|
||||
* is received, data is placed at an appriate offset added to this.
|
||||
*/
|
||||
|
||||
uint16_t i_boffset;
|
||||
|
||||
/* The source MAC address of the fragments being merged */
|
||||
|
||||
struct rimeaddr_s i_fragsrc;
|
||||
|
|
|
|||
|
|
@ -337,6 +337,27 @@ typedef struct pthread_barrier_s pthread_barrier_t;
|
|||
typedef bool pthread_once_t;
|
||||
#define __PTHREAD_ONCE_T_DEFINED 1
|
||||
|
||||
struct pthread_rwlock_s
|
||||
{
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cv;
|
||||
unsigned int num_readers;
|
||||
unsigned int num_writers;
|
||||
bool write_in_progress;
|
||||
};
|
||||
|
||||
typedef struct pthread_rwlock_s pthread_rwlock_t;
|
||||
|
||||
typedef int pthread_rwlockattr_t;
|
||||
|
||||
#define PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, \
|
||||
PTHREAD_COND_INITIALIZER, \
|
||||
0, 0}
|
||||
|
||||
#define PTHREAD_MUTEX_INITIALIZER {NULL, SEM_INITIALIZER(1), -1, \
|
||||
__PTHREAD_MUTEX_DEFAULT_FLAGS, \
|
||||
PTHREAD_MUTEX_DEFAULT, 0}
|
||||
|
||||
#ifdef CONFIG_PTHREAD_CLEANUP
|
||||
/* This type describes the pthread cleanup callback (non-standard) */
|
||||
|
||||
|
|
@ -539,8 +560,8 @@ int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr,
|
|||
|
||||
int pthread_barrier_destroy(FAR pthread_barrier_t *barrier);
|
||||
int pthread_barrier_init(FAR pthread_barrier_t *barrier,
|
||||
FAR const pthread_barrierattr_t *attr,
|
||||
unsigned int count);
|
||||
FAR const pthread_barrierattr_t *attr,
|
||||
unsigned int count);
|
||||
int pthread_barrier_wait(FAR pthread_barrier_t *barrier);
|
||||
|
||||
/* Pthread initialization */
|
||||
|
|
@ -548,6 +569,21 @@ int pthread_barrier_wait(FAR pthread_barrier_t *barrier);
|
|||
int pthread_once(FAR pthread_once_t *once_control,
|
||||
CODE void (*init_routine)(void));
|
||||
|
||||
/* Pthread rwlock */
|
||||
|
||||
int pthread_rwlock_destroy(FAR pthread_rwlock_t *rw_lock);
|
||||
int pthread_rwlock_init(FAR pthread_rwlock_t *rw_lock,
|
||||
FAR const pthread_rwlockattr_t *attr);
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *lock);
|
||||
int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *lock,
|
||||
FAR const struct timespec *abstime);
|
||||
int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *lock);
|
||||
int pthread_rwlock_wrlock(FAR pthread_rwlock_t *lock);
|
||||
int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *lock,
|
||||
FAR const struct timespec *abstime);
|
||||
int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *lock);
|
||||
int pthread_rwlock_unlock(FAR pthread_rwlock_t *lock);
|
||||
|
||||
/* Pthread signal management APIs */
|
||||
|
||||
int pthread_kill(pthread_t thread, int sig);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ CSRCS += pthread_mutexattr_settype.c pthread_mutexattr_gettype.c
|
|||
CSRCS += pthread_mutexattr_setrobust.c pthread_mutexattr_getrobust.c
|
||||
CSRCS += pthread_setcancelstate.c pthread_setcanceltype.c
|
||||
CSRCS += pthread_testcancel.c
|
||||
CSRCS += pthread_rwlock.c pthread_rwlock_rdlock.c pthread_rwlock_wrlock.c
|
||||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
CSRCS += pthread_attr_getaffinity.c pthread_attr_setaffinity.c
|
||||
|
|
|
|||
128
libc/pthread/pthread_rwlock.c
Normal file
128
libc/pthread/pthread_rwlock.c
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/****************************************************************************
|
||||
* libc/pthread/pthread_rwlock.c
|
||||
*
|
||||
* Copyright (C) 2017 Mark Schulte. All rights reserved.
|
||||
* Author: Mark Schulte <mark@mjs.pw>
|
||||
*
|
||||
* 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 NuttX 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 THE COPYRIGHT HOLDERS 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 THE
|
||||
* COPYRIGHT OWNER 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 <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int pthread_rwlock_init(FAR pthread_rwlock_t *lock,
|
||||
FAR const pthread_rwlockattr_t *attr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (attr != NULL)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
lock->num_readers = 0;
|
||||
lock->num_writers = 0;
|
||||
lock->write_in_progress = false;
|
||||
|
||||
err = pthread_cond_init(&lock->cv, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pthread_mutex_init(&lock->lock, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
pthread_cond_destroy(&lock->cv);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int pthread_rwlock_destroy(FAR pthread_rwlock_t *lock)
|
||||
{
|
||||
int cond_err = pthread_cond_destroy(&lock->cv);
|
||||
int mutex_err = pthread_mutex_destroy(&lock->lock);
|
||||
|
||||
if (mutex_err)
|
||||
{
|
||||
return mutex_err;
|
||||
}
|
||||
|
||||
return cond_err;
|
||||
}
|
||||
|
||||
int pthread_rwlock_unlock(FAR pthread_rwlock_t *rw_lock)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_lock(&rw_lock->lock);
|
||||
if (err != 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rw_lock->num_readers > 0)
|
||||
{
|
||||
rw_lock->num_readers--;
|
||||
|
||||
if (rw_lock->num_readers == 0)
|
||||
{
|
||||
err = pthread_cond_broadcast(&rw_lock->cv);
|
||||
}
|
||||
}
|
||||
else if (rw_lock->write_in_progress)
|
||||
{
|
||||
rw_lock->write_in_progress = false;
|
||||
|
||||
err = pthread_cond_broadcast(&rw_lock->cv);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = EINVAL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rw_lock->lock);
|
||||
return err;
|
||||
}
|
||||
143
libc/pthread/pthread_rwlock_rdlock.c
Normal file
143
libc/pthread/pthread_rwlock_rdlock.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/****************************************************************************
|
||||
* libc/pthread/pthread_rwlockread.c
|
||||
*
|
||||
* Copyright (C) 2017 Mark Schulte. All rights reserved.
|
||||
* Author: Mark Schulte <mark@mjs.pw>
|
||||
*
|
||||
* 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 NuttX 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 THE COPYRIGHT HOLDERS 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 THE
|
||||
* COPYRIGHT OWNER 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 <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int tryrdlock(FAR pthread_rwlock_t *rw_lock)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (rw_lock->num_writers > 0 || rw_lock->write_in_progress)
|
||||
{
|
||||
err = EBUSY;
|
||||
}
|
||||
else if (rw_lock->num_readers == UINT_MAX)
|
||||
{
|
||||
err = EAGAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
rw_lock->num_readers++;
|
||||
err = OK;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pthread_rwlock_rdlock
|
||||
*
|
||||
* Description:
|
||||
* Locks a read/write lock for reading
|
||||
*
|
||||
* Parameters:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *rw_lock)
|
||||
{
|
||||
int err = pthread_mutex_trylock(&rw_lock->lock);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tryrdlock(rw_lock);
|
||||
|
||||
pthread_mutex_unlock(&rw_lock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
|
||||
FAR const struct timespec *ts)
|
||||
{
|
||||
int err = pthread_mutex_lock(&rw_lock->lock);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
while ((err = tryrdlock(rw_lock)) == EBUSY)
|
||||
{
|
||||
if (ts != NULL)
|
||||
{
|
||||
err = pthread_cond_timedwait(&rw_lock->cv, &rw_lock->lock, ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = pthread_cond_wait(&rw_lock->cv, &rw_lock->lock);
|
||||
}
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rw_lock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int pthread_rwlock_rdlock(FAR pthread_rwlock_t * rw_lock)
|
||||
{
|
||||
return pthread_rwlock_timedrdlock(rw_lock, NULL);
|
||||
}
|
||||
148
libc/pthread/pthread_rwlock_wrlock.c
Normal file
148
libc/pthread/pthread_rwlock_wrlock.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/****************************************************************************
|
||||
* libc/pthread/pthread_rwlockwrite.c
|
||||
*
|
||||
* Copyright (C) 2017 Mark Schulte. All rights reserved.
|
||||
* Author: Mark Schulte <mark@mjs.pw>
|
||||
*
|
||||
* 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 NuttX 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 THE COPYRIGHT HOLDERS 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 THE
|
||||
* COPYRIGHT OWNER 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 <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pthread_rwlock_rdlock
|
||||
*
|
||||
* Description:
|
||||
* Locks a read/write lock for reading
|
||||
*
|
||||
* Parameters:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *rw_lock)
|
||||
{
|
||||
int err = pthread_mutex_trylock(&rw_lock->lock);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rw_lock->num_readers > 0 || rw_lock->write_in_progress)
|
||||
{
|
||||
err = EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
rw_lock->write_in_progress = true;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rw_lock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
|
||||
FAR const struct timespec *ts)
|
||||
{
|
||||
int err = pthread_mutex_lock(&rw_lock->lock);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rw_lock->num_writers == UINT_MAX)
|
||||
{
|
||||
err = EAGAIN;
|
||||
goto exit_with_mutex;
|
||||
}
|
||||
|
||||
rw_lock->num_writers++;
|
||||
|
||||
while (rw_lock->write_in_progress || rw_lock->num_readers > 0)
|
||||
{
|
||||
if (ts != NULL)
|
||||
{
|
||||
err = pthread_cond_timedwait(&rw_lock->cv, &rw_lock->lock, ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = pthread_cond_wait(&rw_lock->cv, &rw_lock->lock);
|
||||
}
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
rw_lock->write_in_progress = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* In case of error, notify any blocked readers. */
|
||||
|
||||
(void) pthread_cond_broadcast(&rw_lock->cv);
|
||||
}
|
||||
|
||||
rw_lock->num_writers--;
|
||||
|
||||
exit_with_mutex:
|
||||
pthread_mutex_unlock(&rw_lock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int pthread_rwlock_wrlock(FAR pthread_rwlock_t *rw_lock)
|
||||
{
|
||||
return pthread_rwlock_timedwrlock(rw_lock, NULL);
|
||||
}
|
||||
|
|
@ -59,6 +59,10 @@
|
|||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/arp.h>
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
# include <nuttx/net/sixlowpan.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IGMP
|
||||
# include <sys/sockio.h>
|
||||
# include <nuttx/net/igmp.h>
|
||||
|
|
@ -702,16 +706,47 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
|
|||
|
||||
/* MAC address operations only make sense if Ethernet is supported */
|
||||
|
||||
#ifdef CONFIG_NET_ETHERNET
|
||||
#if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_NET_6LOWPAN)
|
||||
case SIOCGIFHWADDR: /* Get hardware address */
|
||||
{
|
||||
dev = netdev_ifrdev(req);
|
||||
if (dev)
|
||||
{
|
||||
req->ifr_hwaddr.sa_family = AF_INETX;
|
||||
memcpy(req->ifr_hwaddr.sa_data,
|
||||
dev->d_mac.ether_addr_octet, IFHWADDRLEN);
|
||||
ret = OK;
|
||||
#ifdef CONFIG_NET_ETHERNET
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
if (dev->d_lltype == NET_LL_ETHERNET)
|
||||
#else
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
req->ifr_hwaddr.sa_family = AF_INETX;
|
||||
memcpy(req->ifr_hwaddr.sa_data,
|
||||
dev->d_mac.ether_addr_octet, IFHWADDRLEN);
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
if (dev->d_lltype == NET_LL_IEEE802154)
|
||||
#else
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
FAR struct ieee802154_driver_s *ieee =
|
||||
(FAR struct ieee802154_driver_s *)dev;
|
||||
|
||||
req->ifr_hwaddr.sa_family = AF_INETX;
|
||||
memcpy(req->ifr_hwaddr.sa_data, ieee->i_nodeaddr.u8,
|
||||
CONFIG_NET_6LOWPAN_RIMEADDR_SIZE);
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nerr("Unsupported link layer\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -721,9 +756,40 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
|
|||
dev = netdev_ifrdev(req);
|
||||
if (dev)
|
||||
{
|
||||
memcpy(dev->d_mac.ether_addr_octet,
|
||||
req->ifr_hwaddr.sa_data, IFHWADDRLEN);
|
||||
ret = OK;
|
||||
#ifdef CONFIG_NET_ETHERNET
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
if (dev->d_lltype == NET_LL_ETHERNET)
|
||||
#else
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
memcpy(dev->d_mac.ether_addr_octet,
|
||||
req->ifr_hwaddr.sa_data, IFHWADDRLEN);
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
if (dev->d_lltype == NET_LL_IEEE802154)
|
||||
#else
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
FAR struct ieee802154_driver_s *ieee =
|
||||
(FAR struct ieee802154_driver_s *)dev;
|
||||
|
||||
req->ifr_hwaddr.sa_family = AF_INETX;
|
||||
memcpy(ieee->i_nodeaddr.u8, req->ifr_hwaddr.sa_data,
|
||||
CONFIG_NET_6LOWPAN_RIMEADDR_SIZE);
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nerr("Unsupported link layer\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -101,17 +101,15 @@
|
|||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* Input Parameters:
|
||||
* ieee - Pointer to IEEE802.15.4 MAC driver structure.
|
||||
* destip - Pointer to the IPv6 header to "compress"
|
||||
* fptr - Pointer to the beginning of the frame under construction
|
||||
* ipv6hdr - Pointer to the IPv6 header to "compress"
|
||||
* fptr - Pointer to the beginning of the frame under construction
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee,
|
||||
FAR const struct ipv6_hdr_s *destip,
|
||||
static void sixlowpan_compress_ipv6hdr(FAR const struct ipv6_hdr_s *ipv6hdr,
|
||||
FAR uint8_t *fptr)
|
||||
{
|
||||
/* Indicate the IPv6 dispatch and length */
|
||||
|
|
@ -121,11 +119,101 @@ static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee,
|
|||
|
||||
/* Copy the IPv6 header and adjust pointers */
|
||||
|
||||
memcpy(&fptr[g_frame_hdrlen] , destip, IPv6_HDRLEN);
|
||||
memcpy(&fptr[g_frame_hdrlen] , ipv6hdr, IPv6_HDRLEN);
|
||||
g_frame_hdrlen += IPv6_HDRLEN;
|
||||
g_uncomp_hdrlen += IPv6_HDRLEN;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sixlowpan_copy_protohdr
|
||||
*
|
||||
* Description:
|
||||
* The IPv6 header should have already been processed (as reflected in the
|
||||
* g_uncomphdrlen). But we probably still need to copy the following
|
||||
* protocol header.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipv6hdr - Pointer to the IPv6 header to "compress"
|
||||
* fptr - Pointer to the beginning of the frame under construction
|
||||
*
|
||||
* Returned Value:
|
||||
* None. But g_frame_hdrlen and g_uncomp_hdrlen updated.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sixlowpan_copy_protohdr(FAR const struct ipv6_hdr_s *ipv6hdr,
|
||||
FAR uint8_t *fptr)
|
||||
{
|
||||
uint16_t combined;
|
||||
uint16_t protosize;
|
||||
uint16_t copysize;
|
||||
|
||||
/* What is the total size of the IPv6 + protocol header? */
|
||||
|
||||
switch (ipv6hdr->proto)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP
|
||||
case IP_PROTO_TCP:
|
||||
{
|
||||
FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6hdr)->tcp;
|
||||
|
||||
/* The TCP header length is encoded in the top 4 bits of the
|
||||
* tcpoffset field (in units of 32-bit words).
|
||||
*/
|
||||
|
||||
protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
|
||||
combined = sizeof(struct ipv6_hdr_s) + protosize;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_UDP
|
||||
case IP_PROTO_UDP:
|
||||
protosize = sizeof(struct udp_hdr_s);
|
||||
combined = sizeof(struct ipv6udp_hdr_s);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_ICMPv6
|
||||
case IP_PROTO_ICMP6:
|
||||
protosize = sizeof(struct icmpv6_hdr_s);
|
||||
combined = sizeof(struct ipv6icmp_hdr_s);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
nwarn("WARNING: Unrecognized proto: %u\n", ipv6hdr->proto);
|
||||
protosize = 0;
|
||||
combined = sizeof(struct ipv6_hdr_s);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the remaining protocol header. */
|
||||
|
||||
if (g_uncomp_hdrlen > IPv6_HDRLEN)
|
||||
{
|
||||
nwarn("WARNING: Protocol header not copied: "
|
||||
"g_uncomp_hdren=%u IPv6_HDRLEN=%u\n",
|
||||
g_uncomp_hdrlen, IPv6_HDRLEN);
|
||||
return;
|
||||
}
|
||||
|
||||
copysize = combined - g_uncomp_hdrlen;
|
||||
if (copysize != protosize)
|
||||
{
|
||||
nwarn("WARNING: Protocol header size mismatch: "
|
||||
"g_uncomp_hdren=%u copysize=%u protosize=%u\n",
|
||||
g_uncomp_hdrlen, copysize, protosize);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)ipv6hdr + g_uncomp_hdrlen,
|
||||
copysize);
|
||||
|
||||
g_frame_hdrlen += copysize;
|
||||
g_uncomp_hdrlen += copysize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -146,7 +234,7 @@ static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee,
|
|||
*
|
||||
* Input Parameters:
|
||||
* ieee - The IEEE802.15.4 MAC driver instance
|
||||
* ipv6hdr - IPv6 header followed by TCP or UDP header.
|
||||
* ipv6hdr - IPv6 header followed by TCP, UDP, or ICMPv6 header.
|
||||
* buf - Beginning of the packet packet to send (with IPv6 + protocol
|
||||
* headers)
|
||||
* buflen - Length of data to send (include IPv6 and protocol headers)
|
||||
|
|
@ -172,6 +260,8 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
FAR uint8_t *fptr;
|
||||
int framer_hdrlen;
|
||||
struct rimeaddr_s bcastmac;
|
||||
uint16_t pktlen;
|
||||
uint16_t paysize;
|
||||
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
||||
uint16_t outlen = 0;
|
||||
#endif
|
||||
|
|
@ -267,7 +357,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
{
|
||||
/* Small.. use IPv6 dispatch (no compression) */
|
||||
|
||||
sixlowpan_compress_ipv6hdr(ieee, destip, fptr);
|
||||
sixlowpan_compress_ipv6hdr(destip, fptr);
|
||||
}
|
||||
|
||||
ninfo("Header of length %d\n", g_frame_hdrlen);
|
||||
|
|
@ -276,9 +366,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
|
||||
/* Check if we need to fragment the packet into several frames */
|
||||
|
||||
if ((int)buflen - (int)g_uncomp_hdrlen >
|
||||
(int)CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen -
|
||||
(int)g_frame_hdrlen)
|
||||
if (buflen > (CONFIG_NET_6LOWPAN_MAXPAYLOAD - g_frame_hdrlen))
|
||||
{
|
||||
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
||||
/* ieee->i_framelist will hold the generated frames; frames will be
|
||||
|
|
@ -286,6 +374,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
*/
|
||||
|
||||
FAR struct iob_s *qtail;
|
||||
FAR uint8_t *frame1;
|
||||
int verify;
|
||||
|
||||
/* The outbound IPv6 packet is too large to fit into a single 15.4
|
||||
|
|
@ -295,7 +384,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
* The following fragments contain only the fragn dispatch.
|
||||
*/
|
||||
|
||||
ninfo("Fragmentation sending packet length %d\n", buflen);
|
||||
ninfo("Sending fragmented packet length %d\n", buflen);
|
||||
|
||||
/* Create 1st Fragment */
|
||||
/* Add the frame header using the pre-allocated IOB. */
|
||||
|
|
@ -304,7 +393,9 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
DEBUGASSERT(verify == framer_hdrlen);
|
||||
UNUSED(verify);
|
||||
|
||||
/* Move HC1/HC06/IPv6 header */
|
||||
/* Move HC1/HC06/IPv6 header to make space for the FRAG1 header at the
|
||||
* beginning of the frame.
|
||||
*/
|
||||
|
||||
memmove(fptr + SIXLOWPAN_FRAG1_HDR_LEN, fptr, g_frame_hdrlen);
|
||||
|
||||
|
|
@ -323,27 +414,31 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
* bytes for all subsequent headers.
|
||||
*/
|
||||
|
||||
pktlen = buflen + g_uncomp_hdrlen;
|
||||
PUTINT16(fptr, RIME_FRAG_DISPATCH_SIZE,
|
||||
((SIXLOWPAN_DISPATCH_FRAG1 << 8) | buflen));
|
||||
((SIXLOWPAN_DISPATCH_FRAG1 << 8) | pktlen));
|
||||
PUTINT16(fptr, RIME_FRAG_TAG, ieee->i_dgramtag);
|
||||
ieee->i_dgramtag++;
|
||||
|
||||
/* Copy payload and enqueue */
|
||||
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
|
||||
|
||||
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
|
||||
g_rime_payloadlen =
|
||||
(CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen - g_frame_hdrlen) & 0xf8;
|
||||
/* Copy protocol header that follows the IPv6 header */
|
||||
|
||||
memcpy(fptr + g_frame_hdrlen,
|
||||
(FAR uint8_t *)destip + g_uncomp_hdrlen, g_rime_payloadlen);
|
||||
iob->io_len += g_rime_payloadlen + g_frame_hdrlen;
|
||||
sixlowpan_copy_protohdr(destip, fptr);
|
||||
|
||||
/* Copy payload and enqueue. NOTE that the size is a multiple of eight
|
||||
* bytes.
|
||||
*/
|
||||
|
||||
paysize = (CONFIG_NET_6LOWPAN_MAXPAYLOAD - g_frame_hdrlen) & ~7;
|
||||
memcpy(fptr + g_frame_hdrlen, buf, paysize);
|
||||
|
||||
/* Set outlen to what we already sent from the IP payload */
|
||||
|
||||
outlen = g_rime_payloadlen + g_uncomp_hdrlen;
|
||||
iob->io_len = paysize + g_frame_hdrlen;
|
||||
outlen = paysize;
|
||||
|
||||
ninfo("First fragment: length %d, tag %d\n",
|
||||
g_rime_payloadlen, ieee->i_dgramtag);
|
||||
paysize, ieee->i_dgramtag);
|
||||
sixlowpan_dumpbuffer("Outgoing frame",
|
||||
(FAR const uint8_t *)iob->io_data, iob->io_len);
|
||||
|
||||
|
|
@ -358,10 +453,11 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
|
||||
/* Create following fragments */
|
||||
|
||||
g_frame_hdrlen = SIXLOWPAN_FRAGN_HDR_LEN;
|
||||
|
||||
frame1 = iob->io_data;
|
||||
while (outlen < buflen)
|
||||
{
|
||||
uint16_t fragn_hdrlen;
|
||||
|
||||
/* Allocate an IOB to hold the next fragment, waiting if
|
||||
* necessary.
|
||||
*/
|
||||
|
|
@ -377,47 +473,45 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
iob->io_pktlen = 0;
|
||||
fptr = iob->io_data;
|
||||
|
||||
/* Add the frame header */
|
||||
/* Copy the frame header from first frame, into the correct
|
||||
* location after the FRAGN header.
|
||||
*/
|
||||
|
||||
verify = sixlowpan_framecreate(ieee, iob, ieee->i_panid);
|
||||
DEBUGASSERT(verify == framer_hdrlen);
|
||||
UNUSED(verify);
|
||||
memmove(fptr + SIXLOWPAN_FRAGN_HDR_LEN,
|
||||
frame1 + SIXLOWPAN_FRAG1_HDR_LEN,
|
||||
framer_hdrlen);
|
||||
fragn_hdrlen = framer_hdrlen;
|
||||
|
||||
/* Move HC1/HC06/IPv6 header */
|
||||
|
||||
memmove(fptr + SIXLOWPAN_FRAGN_HDR_LEN, fptr, g_frame_hdrlen);
|
||||
|
||||
/* Setup up the fragment header */
|
||||
/* Setup up the FRAGN header at the beginning of the frame */
|
||||
|
||||
PUTINT16(fptr, RIME_FRAG_DISPATCH_SIZE,
|
||||
((SIXLOWPAN_DISPATCH_FRAGN << 8) | buflen));
|
||||
((SIXLOWPAN_DISPATCH_FRAGN << 8) | pktlen));
|
||||
PUTINT16(fptr, RIME_FRAG_TAG, ieee->i_dgramtag);
|
||||
fptr[RIME_FRAG_OFFSET] = outlen >> 3;
|
||||
|
||||
fragn_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
|
||||
|
||||
/* Copy payload and enqueue */
|
||||
/* Check for the last fragment */
|
||||
|
||||
if (buflen - outlen < g_rime_payloadlen)
|
||||
paysize = (CONFIG_NET_6LOWPAN_MAXPAYLOAD - fragn_hdrlen) &
|
||||
SIXLOWPAN_DISPATCH_FRAG_MASK;
|
||||
if (buflen - outlen < paysize)
|
||||
{
|
||||
/* Last fragment */
|
||||
/* Last fragment, truncate to the correct length */
|
||||
|
||||
g_rime_payloadlen = buflen - outlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_rime_payloadlen =
|
||||
(CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen - g_frame_hdrlen) & 0xf8;
|
||||
paysize = buflen - outlen;
|
||||
}
|
||||
|
||||
memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)destip + outlen,
|
||||
g_rime_payloadlen);
|
||||
iob->io_len = g_rime_payloadlen + g_frame_hdrlen;
|
||||
memcpy(fptr + fragn_hdrlen, buf + outlen, paysize);
|
||||
|
||||
/* Set outlen to what we already sent from the IP payload */
|
||||
|
||||
outlen += (g_rime_payloadlen + g_uncomp_hdrlen);
|
||||
iob->io_len = paysize + fragn_hdrlen;
|
||||
outlen += paysize;
|
||||
|
||||
ninfo("sixlowpan output: fragment offset %d, length %d, tag %d\n",
|
||||
outlen >> 3, g_rime_payloadlen, ieee->i_dgramtag);
|
||||
ninfo("Fragment offset=%d, paysize=%d, i_dgramtag=%d\n",
|
||||
outlen >> 3, paysize, ieee->i_dgramtag);
|
||||
sixlowpan_dumpbuffer("Outgoing frame",
|
||||
(FAR const uint8_t *)iob->io_data,
|
||||
iob->io_len);
|
||||
|
|
@ -425,11 +519,16 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
/* Add the next frame to the tail of the IOB queue */
|
||||
|
||||
qtail->io_flink = iob;
|
||||
qtail = iob;
|
||||
|
||||
/* Keep track of the total amount of data queue */
|
||||
|
||||
ieee->i_framelist->io_pktlen += iob->io_len;
|
||||
}
|
||||
|
||||
/* Update the datagram TAG value */
|
||||
|
||||
ieee->i_dgramtag++;
|
||||
#else
|
||||
nerr("ERROR: Packet too large: %d\n", buflen);
|
||||
nerr(" Cannot to be sent without fragmentation support\n");
|
||||
|
|
@ -452,11 +551,14 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
|
|||
DEBUGASSERT(verify == framer_hdrlen);
|
||||
UNUSED(verify);
|
||||
|
||||
/* Copy protocol header that follows the IPv6 header */
|
||||
|
||||
sixlowpan_copy_protohdr(destip, fptr);
|
||||
|
||||
/* Copy the payload and queue */
|
||||
|
||||
memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)destip + g_uncomp_hdrlen,
|
||||
buflen - g_uncomp_hdrlen);
|
||||
iob->io_len = buflen - g_uncomp_hdrlen + g_frame_hdrlen;
|
||||
memcpy(fptr + g_frame_hdrlen, buf, buflen);
|
||||
iob->io_len = buflen + g_frame_hdrlen;
|
||||
|
||||
ninfo("Non-fragmented: length %d\n", iob->io_len);
|
||||
sixlowpan_dumpbuffer("Outgoing frame",
|
||||
|
|
|
|||
|
|
@ -54,15 +54,6 @@
|
|||
* during that processing
|
||||
*/
|
||||
|
||||
/* The length of the payload in the Rime buffer.
|
||||
*
|
||||
* The payload is what comes after the compressed or uncompressed headers
|
||||
* (can be the IP payload if the IP header only is compressed or the UDP
|
||||
* payload if the UDP header is also compressed)
|
||||
*/
|
||||
|
||||
uint8_t g_rime_payloadlen;
|
||||
|
||||
/* g_uncomp_hdrlen is the length of the headers before compression (if HC2
|
||||
* is used this includes the UDP header in addition to the IP header).
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@
|
|||
*
|
||||
* Input Parmeters:
|
||||
* ieee - A reference to the IEE802.15.4 network device state
|
||||
* ipv6 - The IPv6 header to be compressed
|
||||
* ipv6 - The IPv6 header followd by TCP, UDP, or ICMPv6 header to be
|
||||
* compressed
|
||||
* destmac - L2 destination address, needed to compress the IP
|
||||
* destination field
|
||||
* fptr - Pointer to frame to be compressed.
|
||||
|
|
@ -189,7 +190,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
|
|||
#if CONFIG_NET_UDP
|
||||
case IP_PROTO_UDP:
|
||||
{
|
||||
FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev);
|
||||
FAR struct udp_hdr_s *udp =
|
||||
&(((FAR struct ipv6udp_hdr_s *)ipv6)->udp);
|
||||
|
||||
/* Try to compress UDP header (we do only full compression).
|
||||
* This is feasible if both src and dest ports are between
|
||||
|
|
@ -199,10 +201,10 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
|
|||
|
||||
ninfo("local/remote port %u/%u\n", udp->srcport, udp->destport);
|
||||
|
||||
if (htons(udp->srcport) >= CONFIG_NET_6LOWPAN_MINPORT &&
|
||||
htons(udp->srcport) < (CONFIG_NET_6LOWPAN_MINPORT + 16) &&
|
||||
htons(udp->destport) >= CONFIG_NET_6LOWPAN_MINPORT &&
|
||||
htons(udp->destport) < (CONFIG_NET_6LOWPAN_MINPORT + 16))
|
||||
if (ntohs(udp->srcport) >= CONFIG_NET_6LOWPAN_MINPORT &&
|
||||
ntohs(udp->srcport) < (CONFIG_NET_6LOWPAN_MINPORT + 16) &&
|
||||
ntohs(udp->destport) >= CONFIG_NET_6LOWPAN_MINPORT &&
|
||||
ntohs(udp->destport) < (CONFIG_NET_6LOWPAN_MINPORT + 16))
|
||||
{
|
||||
FAR uint8_t *hcudp = fptr + g_frame_hdrlen;
|
||||
|
||||
|
|
@ -215,8 +217,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
|
|||
hcudp[RIME_HC1_HC_UDP_UDP_ENCODING] = 0xe0;
|
||||
hcudp[RIME_HC1_HC_UDP_TTL] = ipv6->ttl;
|
||||
hcudp[RIME_HC1_HC_UDP_PORTS] =
|
||||
(uint8_t)((htons(udp->srcport) - CONFIG_NET_6LOWPAN_MINPORT) << 4) +
|
||||
(uint8_t)((htons(udp->destport) - CONFIG_NET_6LOWPAN_MINPORT));
|
||||
(uint8_t)((ntohs(udp->srcport) - CONFIG_NET_6LOWPAN_MINPORT) << 4) +
|
||||
(uint8_t)((ntohs(udp->destport) - CONFIG_NET_6LOWPAN_MINPORT));
|
||||
|
||||
memcpy(&hcudp[RIME_HC1_HC_UDP_CHKSUM], &udp->udpchksum, 2);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
/* Buffer access helpers */
|
||||
|
||||
#define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf))
|
||||
#define TCPBUF(dev) ((FAR struct tcp_hdr_s *)&(dev)->d_buf[IPv6_HDRLEN])
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
|
|
@ -111,12 +112,26 @@
|
|||
|
||||
int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr)
|
||||
{
|
||||
uint16_t hdrlen;
|
||||
uint16_t hdrlen = 0;
|
||||
uint8_t addrmode;
|
||||
uint8_t tmp;
|
||||
|
||||
/* Check for a fragment header preceding the IEEE802.15.4 FCF */
|
||||
|
||||
tmp = *fptr & SIXLOWPAN_DISPATCH_FRAG_MASK;
|
||||
if (tmp == SIXLOWPAN_DISPATCH_FRAG1)
|
||||
{
|
||||
hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
|
||||
}
|
||||
else if (tmp == SIXLOWPAN_DISPATCH_FRAGN)
|
||||
{
|
||||
hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
|
||||
}
|
||||
|
||||
/* Minimum header: 2 byte FCF + 1 byte sequence number */
|
||||
|
||||
hdrlen = 3;
|
||||
fptr += hdrlen;
|
||||
hdrlen += 3;
|
||||
|
||||
/* Account for destination address size */
|
||||
|
||||
|
|
@ -209,10 +224,9 @@ int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr)
|
|||
static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
||||
FAR struct iob_s *iob)
|
||||
{
|
||||
FAR uint8_t *payptr; /* Pointer to the frame payload */
|
||||
FAR uint8_t *hc1; /* Convenience pointer to HC1 data */
|
||||
|
||||
uint16_t fragsize = 0; /* Size of the IP packet (read from fragment) */
|
||||
uint16_t paysize; /* Size of the data payload */
|
||||
uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */
|
||||
int reqsize; /* Required buffer size */
|
||||
int hdrsize; /* Size of the IEEE802.15.4 header */
|
||||
|
|
@ -220,12 +234,13 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
||||
bool isfrag = false;
|
||||
bool isfirstfrag = false;
|
||||
bool islastfrag = false;
|
||||
uint16_t fragtag = 0; /* Tag of the fragment */
|
||||
systime_t elapsed; /* Elapsed time */
|
||||
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
||||
|
||||
/* Get a pointer to the payload following the IEEE802.15.4 frame header. */
|
||||
/* Get a pointer to the payload following the IEEE802.15.4 frame header(s).
|
||||
* This size includes both fragmentation and FCF headers.
|
||||
*/
|
||||
|
||||
hdrsize = sixlowpan_recv_hdrlen(iob->io_data);
|
||||
if (hdrsize < 0)
|
||||
|
|
@ -241,16 +256,13 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
g_uncomp_hdrlen = 0;
|
||||
g_frame_hdrlen = hdrsize;
|
||||
|
||||
/* Payload starts after the IEEE802.15.4 header */
|
||||
|
||||
payptr = &iob->io_data[hdrsize];
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
||||
/* Since we don't support the mesh and broadcast header, the first header
|
||||
* we look for is the fragmentation header
|
||||
* we look for is the fragmentation header. NOTE that g_frame_hdrlen
|
||||
* already includes the fragementation header, if presetn.
|
||||
*/
|
||||
|
||||
switch ((GETINT16(payptr, RIME_FRAG_DISPATCH_SIZE) & 0xf800) >> 8)
|
||||
switch ((GETINT16(iob->io_data, RIME_FRAG_DISPATCH_SIZE) & 0xf800) >> 8)
|
||||
{
|
||||
/* First fragment of new reassembly */
|
||||
|
||||
|
|
@ -258,15 +270,12 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
{
|
||||
/* Set up for the reassembly */
|
||||
|
||||
fragoffset = 0;
|
||||
fragsize = GETINT16(payptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
|
||||
fragtag = GETINT16(payptr, RIME_FRAG_TAG);
|
||||
fragsize = GETINT16(iob->io_data, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
|
||||
fragtag = GETINT16(iob->io_data, RIME_FRAG_TAG);
|
||||
|
||||
ninfo("FRAG1: size %d, tag %d, offset %d\n",
|
||||
ninfo("FRAG1: fragsize=%d fragtag=%d fragoffset=%d\n",
|
||||
fragsize, fragtag, fragoffset);
|
||||
|
||||
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
|
||||
|
||||
/* Indicate the first fragment of the reassembly */
|
||||
|
||||
isfirstfrag = true;
|
||||
|
|
@ -278,32 +287,18 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
{
|
||||
/* Set offset, tag, size. Offset is in units of 8 bytes. */
|
||||
|
||||
fragoffset = payptr[RIME_FRAG_OFFSET];
|
||||
fragtag = GETINT16(payptr, RIME_FRAG_TAG);
|
||||
fragsize = GETINT16(payptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
|
||||
fragoffset = iob->io_data[RIME_FRAG_OFFSET];
|
||||
fragtag = GETINT16(iob->io_data, RIME_FRAG_TAG);
|
||||
fragsize = GETINT16(iob->io_data, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
|
||||
|
||||
ninfo("FRAGN: size %d, tag %d, offset %d\n",
|
||||
ninfo("FRAGN: fragsize=%d fragtag=%d fragoffset=%d\n",
|
||||
fragsize, fragtag, fragoffset);
|
||||
|
||||
g_frame_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
|
||||
|
||||
ninfo("FRAGN: i_accumlen %d g_rime_payloadlen %d fragsize %d\n",
|
||||
ninfo("FRAGN: i_accumlen=%d paysize=%u fragsize=%u\n",
|
||||
ieee->i_accumlen, iob->io_len - g_frame_hdrlen, fragsize);
|
||||
|
||||
/* Indicate that this frame is a another fragment for reassembly */
|
||||
|
||||
isfrag = true;
|
||||
|
||||
/* Check if it is the last fragement to be processed.
|
||||
*
|
||||
* If this is the last fragment, we may shave off any extrenous
|
||||
* bytes at the end. We must be liberal in what we accept.
|
||||
*/
|
||||
|
||||
if (ieee->i_accumlen + iob->io_len - g_frame_hdrlen >= fragsize)
|
||||
{
|
||||
islastfrag = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -392,6 +387,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
* compression dispatch logic.
|
||||
*/
|
||||
|
||||
g_uncomp_hdrlen = ieee->i_boffset;
|
||||
goto copypayload;
|
||||
}
|
||||
}
|
||||
|
|
@ -412,29 +408,22 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
return OK;
|
||||
}
|
||||
|
||||
/* Start reassembly if we received a non-zero length, first fragment */
|
||||
/* Drop the packet if it cannot fit into the d_buf */
|
||||
|
||||
if (fragsize > 0)
|
||||
if (fragsize > CONFIG_NET_6LOWPAN_MTU)
|
||||
{
|
||||
/* Drop the packet if it cannot fit into the d_buf */
|
||||
|
||||
if (fragsize > CONFIG_NET_6LOWPAN_MTU)
|
||||
{
|
||||
nwarn("WARNING: Reassembled packet size exeeds CONFIG_NET_6LOWPAN_MTU\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Set up for the reassembly */
|
||||
|
||||
ieee->i_pktlen = fragsize;
|
||||
ieee->i_reasstag = fragtag;
|
||||
ieee->i_time = clock_systimer();
|
||||
|
||||
ninfo("Starting reassembly: i_pktlen %d, i_pktlen %d\n",
|
||||
ieee->i_pktlen, ieee->i_reasstag);
|
||||
|
||||
rimeaddr_copy(&ieee->i_fragsrc, &g_pktaddrs[PACKETBUF_ADDR_SENDER]);
|
||||
nwarn("WARNING: Reassembled packet size exeeds CONFIG_NET_6LOWPAN_MTU\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
ieee->i_pktlen = fragsize;
|
||||
ieee->i_reasstag = fragtag;
|
||||
ieee->i_time = clock_systimer();
|
||||
|
||||
ninfo("Starting reassembly: i_pktlen %u, i_reasstag %d\n",
|
||||
ieee->i_pktlen, ieee->i_reasstag);
|
||||
|
||||
rimeaddr_copy(&ieee->i_fragsrc, &g_pktaddrs[PACKETBUF_ADDR_SENDER]);
|
||||
}
|
||||
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
||||
|
||||
|
|
@ -445,7 +434,13 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
|
||||
if ((hc1[RIME_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC)
|
||||
{
|
||||
FAR uint8_t *payptr;
|
||||
|
||||
ninfo("IPHC Dispatch\n");
|
||||
|
||||
/* Payload starts after the IEEE802.15.4 header(s) */
|
||||
|
||||
payptr = &iob->io_data[g_frame_hdrlen];
|
||||
sixlowpan_uncompresshdr_hc06(ieee, fragsize, iob, payptr);
|
||||
}
|
||||
else
|
||||
|
|
@ -454,7 +449,13 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
|
||||
if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_HC1)
|
||||
{
|
||||
FAR uint8_t *payptr;
|
||||
|
||||
ninfo("HC1 Dispatch\n");
|
||||
|
||||
/* Payload starts after the IEEE802.15.4 header(s) */
|
||||
|
||||
payptr = &iob->io_data[g_frame_hdrlen];
|
||||
sixlowpan_uncompresshdr_hc1(ieee, fragsize, iob, payptr);
|
||||
}
|
||||
else
|
||||
|
|
@ -467,16 +468,9 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
ninfo("IPv6 Dispatch\n");
|
||||
g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN;
|
||||
|
||||
/* payptr was set up to begin just after the IPHC bytes. However,
|
||||
* those bytes are not present for the case of IPv6 dispatch. Just
|
||||
* reset back to the begnning of the buffer.
|
||||
*/
|
||||
|
||||
payptr = iob->io_data;
|
||||
|
||||
/* Put uncompressed IP header in d_buf. */
|
||||
|
||||
memcpy(ipv6, payptr + g_frame_hdrlen, IPv6_HDRLEN);
|
||||
memcpy(ipv6, iob->io_data + g_frame_hdrlen, IPv6_HDRLEN);
|
||||
|
||||
/* Update g_uncomp_hdrlen and g_frame_hdrlen. */
|
||||
|
||||
|
|
@ -492,6 +486,18 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
||||
/* Non-fragmented and FRAG1 frames pass through here. Remember the
|
||||
* offset from the beginning of d_buf where be begin placing the data
|
||||
* payload.
|
||||
*/
|
||||
|
||||
if (isfirstfrag)
|
||||
{
|
||||
ieee->i_boffset = g_uncomp_hdrlen;
|
||||
}
|
||||
|
||||
/* We branch to here on all good FRAGN frames */
|
||||
|
||||
copypayload:
|
||||
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
||||
|
||||
|
|
@ -501,28 +507,28 @@ copypayload:
|
|||
* and g_frame_hdrlen are non-zerio, fragoffset is.
|
||||
*/
|
||||
|
||||
g_rime_payloadlen = iob->io_len - g_frame_hdrlen;
|
||||
if (g_rime_payloadlen > CONFIG_NET_6LOWPAN_MTU)
|
||||
paysize = iob->io_len - g_frame_hdrlen;
|
||||
if (paysize > CONFIG_NET_6LOWPAN_MTU)
|
||||
{
|
||||
nwarn("WARNING: Packet dropped due to payload (%u) > packet buffer (%u)\n",
|
||||
g_rime_payloadlen, CONFIG_NET_6LOWPAN_MTU);
|
||||
paysize, CONFIG_NET_6LOWPAN_MTU);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Sanity-check size of incoming packet to avoid buffer overflow */
|
||||
|
||||
reqsize = g_uncomp_hdrlen + (uint16_t) (fragoffset << 3) + g_rime_payloadlen;
|
||||
reqsize = g_uncomp_hdrlen + (fragoffset << 3) + paysize;
|
||||
if (reqsize > CONFIG_NET_6LOWPAN_MTU)
|
||||
{
|
||||
ninfo("Required buffer size: %d+%d+%d=%d Available: %d\n",
|
||||
g_uncomp_hdrlen, (int)(fragoffset << 3), g_rime_payloadlen,
|
||||
ninfo("Required buffer size: %u+%u+%u=%u Available=%u\n",
|
||||
g_uncomp_hdrlen, (fragoffset << 3), paysize,
|
||||
reqsize, CONFIG_NET_6LOWPAN_MTU);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy((FAR uint8_t *)ieee->i_dev.d_buf + g_uncomp_hdrlen +
|
||||
(int)(fragoffset << 3), payptr + g_frame_hdrlen,
|
||||
g_rime_payloadlen);
|
||||
memcpy(ieee->i_dev.d_buf + g_uncomp_hdrlen + (fragoffset << 3),
|
||||
iob->io_data + g_frame_hdrlen,
|
||||
paysize);
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
||||
/* Update ieee->i_accumlen if the frame is a fragment, ieee->i_pktlen
|
||||
|
|
@ -531,42 +537,27 @@ copypayload:
|
|||
|
||||
if (isfrag)
|
||||
{
|
||||
/* Add the size of the header only for the first fragment. */
|
||||
|
||||
if (isfirstfrag)
|
||||
{
|
||||
ieee->i_accumlen += g_uncomp_hdrlen;
|
||||
}
|
||||
|
||||
/* For the last fragment, we are OK if there is extraneous bytes at the
|
||||
* end of the packet.
|
||||
/* Check if it is the last fragment to be processed.
|
||||
*
|
||||
* If this is the last fragment, we may shave off any extrenous
|
||||
* bytes at the end. We must be liberal in what we accept.
|
||||
*/
|
||||
|
||||
if (islastfrag)
|
||||
{
|
||||
ieee->i_accumlen = fragsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ieee->i_accumlen += g_rime_payloadlen;
|
||||
}
|
||||
|
||||
ninfo("i_accumlen %d, g_rime_payloadlen %d\n",
|
||||
ieee->i_accumlen, g_rime_payloadlen);
|
||||
ieee->i_accumlen = g_uncomp_hdrlen + (fragoffset << 3) + paysize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ieee->i_pktlen = g_rime_payloadlen + g_uncomp_hdrlen;
|
||||
ieee->i_pktlen = paysize + g_uncomp_hdrlen;
|
||||
}
|
||||
|
||||
/* If we have a full IP packet in sixlowpan_buf, deliver it to
|
||||
* the IP stack
|
||||
*/
|
||||
|
||||
ninfo("sixlowpan_init i_accumlen %d, ieee->i_pktlen %d\n",
|
||||
ieee->i_accumlen, ieee->i_pktlen);
|
||||
ninfo("i_accumlen=%d i_pktlen=%d paysize=%d\n",
|
||||
ieee->i_accumlen, ieee->i_pktlen, paysize);
|
||||
|
||||
if (ieee->i_accumlen == 0 || ieee->i_accumlen == ieee->i_pktlen)
|
||||
if (ieee->i_accumlen == 0 || ieee->i_accumlen >= ieee->i_pktlen)
|
||||
{
|
||||
ninfo("IP packet ready (length %d)\n", ieee->i_pktlen);
|
||||
|
||||
|
|
@ -580,7 +571,7 @@ copypayload:
|
|||
#else
|
||||
/* Deliver the packet to the IP stack */
|
||||
|
||||
ieee->i_dev.d_len = g_rime_payloadlen + g_uncomp_hdrlen;
|
||||
ieee->i_dev.d_len = paysize + g_uncomp_hdrlen;
|
||||
return INPUT_COMPLETE;
|
||||
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
||||
}
|
||||
|
|
@ -706,6 +697,10 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
|
|||
|
||||
ret = sixlowpan_frame_process(ieee, iob);
|
||||
|
||||
/* Free the IOB the held the consumed frame */
|
||||
|
||||
iob_free(iob);
|
||||
|
||||
/* Was the frame successfully processed? Is the packet in d_buf fully
|
||||
* reassembled?
|
||||
*/
|
||||
|
|
@ -734,7 +729,7 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
|
|||
* layer protocol header.
|
||||
*/
|
||||
|
||||
ipv6hdr = (FAR struct ipv6_hdr_s *)(ieee->i_dev.d_buf);
|
||||
ipv6hdr = IPv6BUF(&ieee->i_dev);
|
||||
|
||||
/* Get the Rime MAC address of the destination. This
|
||||
* assumes an encoding of the MAC address in the IPv6
|
||||
|
|
@ -749,7 +744,15 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
|
|||
|
||||
if (ipv6hdr->proto != IP_PROTO_TCP)
|
||||
{
|
||||
hdrlen = IPv6_HDRLEN + TCP_HDRLEN;
|
||||
FAR struct tcp_hdr_s *tcp = TCPBUF(&ieee->i_dev);
|
||||
uint16_t tcplen;
|
||||
|
||||
/* The TCP header length is encoded in the top 4 bits
|
||||
* of the tcpoffset field (in units of 32-bit words).
|
||||
*/
|
||||
|
||||
tcplen = ((uint16_t)tcp->tcpoffset >> 4) << 2;
|
||||
hdrlen = IPv6_HDRLEN + tcplen;
|
||||
}
|
||||
else if (ipv6hdr->proto != IP_PROTO_UDP)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -409,15 +409,6 @@ struct frame802154_s
|
|||
|
||||
extern FAR uint8_t *g_rimeptr;
|
||||
|
||||
/* The length of the payload in the Rime buffer.
|
||||
*
|
||||
* The payload is what comes after the compressed or uncompressed headers
|
||||
* (can be the IP payload if the IP header only is compressed or the UDP
|
||||
* payload if the UDP header is also compressed)
|
||||
*/
|
||||
|
||||
extern uint8_t g_rime_payloadlen;
|
||||
|
||||
/* g_uncomp_hdrlen is the length of the headers before compression (if HC2
|
||||
* is used this includes the UDP header in addition to the IP header).
|
||||
*/
|
||||
|
|
@ -446,6 +437,7 @@ extern struct rimeaddr_s g_pktaddrs[PACKETBUF_NUM_ADDRS];
|
|||
|
||||
struct net_driver_s; /* Forward reference */
|
||||
struct ieee802154_driver_s; /* Forward reference */
|
||||
struct devif_callback_s; /* Forward reference */
|
||||
struct ipv6_hdr_s; /* Forward reference */
|
||||
struct rimeaddr_s; /* Forward reference */
|
||||
struct iob_s; /* Forward reference */
|
||||
|
|
@ -466,7 +458,8 @@ struct iob_s; /* Forward reference */
|
|||
*
|
||||
* Input Parameters:
|
||||
* dev - The IEEE802.15.4 MAC network driver interface.
|
||||
* destip - IPv6 plus TCP or UDP headers.
|
||||
* list - Head of callback list for send interrupt
|
||||
* ipv6hdr - IPv6 plus TCP or UDP headers.
|
||||
* buf - Data to send
|
||||
* buflen - Length of data to send
|
||||
* raddr - The MAC address of the destination
|
||||
|
|
@ -484,7 +477,8 @@ struct iob_s; /* Forward reference */
|
|||
****************************************************************************/
|
||||
|
||||
int sixlowpan_send(FAR struct net_driver_s *dev,
|
||||
FAR const struct ipv6_hdr_s *destip, FAR const void *buf,
|
||||
FAR struct devif_callback_s **list,
|
||||
FAR const struct ipv6_hdr_s *ipv6hdr, FAR const void *buf,
|
||||
size_t buflen, FAR const struct rimeaddr_s *raddr,
|
||||
uint16_t timeout);
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ static uint16_t send_interrupt(FAR struct net_driver_s *dev,
|
|||
{
|
||||
DEBUGASSERT((flags & WPAN_POLL) != 0);
|
||||
|
||||
/* Transfer the frame listto the IEEE802.15.4 MAC device */
|
||||
/* Transfer the frame list to the IEEE802.15.4 MAC device */
|
||||
|
||||
sinfo->s_result =
|
||||
sixlowpan_queue_frames((FAR struct ieee802154_driver_s *)dev,
|
||||
|
|
@ -237,6 +237,7 @@ end_wait:
|
|||
*
|
||||
* Input Parameters:
|
||||
* dev - The IEEE802.15.4 MAC network driver interface.
|
||||
* list - Head of callback list for send interrupt
|
||||
* ipv6hdr - IPv6 header followed by TCP or UDP header.
|
||||
* buf - Data to send
|
||||
* len - Length of data to send
|
||||
|
|
@ -255,6 +256,7 @@ end_wait:
|
|||
****************************************************************************/
|
||||
|
||||
int sixlowpan_send(FAR struct net_driver_s *dev,
|
||||
FAR struct devif_callback_s **list,
|
||||
FAR const struct ipv6_hdr_s *ipv6hdr, FAR const void *buf,
|
||||
size_t len, FAR const struct rimeaddr_s *destmac,
|
||||
uint16_t timeout)
|
||||
|
|
@ -283,7 +285,7 @@ int sixlowpan_send(FAR struct net_driver_s *dev,
|
|||
* device related events, no connect-related events.
|
||||
*/
|
||||
|
||||
sinfo.s_cb = devif_callback_alloc(dev, NULL);
|
||||
sinfo.s_cb = devif_callback_alloc(dev, list);
|
||||
if (sinfo.s_cb != NULL)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -312,7 +314,7 @@ int sixlowpan_send(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
devif_dev_callback_free(dev, sinfo.s_cb);
|
||||
devif_conn_callback_free(dev, sinfo.s_cb, list);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ static uint16_t sixlowpan_tcp_chksum(FAR struct ipv6tcp_hdr_s *ipv6tcp,
|
|||
FAR const uint8_t *buf, uint16_t buflen)
|
||||
{
|
||||
uint16_t upperlen;
|
||||
uint16_t tcplen;
|
||||
uint16_t sum;
|
||||
|
||||
/* The length reported in the IPv6 header is the length of the payload
|
||||
|
|
@ -115,9 +116,14 @@ static uint16_t sixlowpan_tcp_chksum(FAR struct ipv6tcp_hdr_s *ipv6tcp,
|
|||
sum = chksum(sum, (FAR uint8_t *)ipv6tcp->ipv6.srcipaddr,
|
||||
2 * sizeof(net_ipv6addr_t));
|
||||
|
||||
/* Sum the TCP header */
|
||||
/* Sum the TCP header
|
||||
*
|
||||
* The TCP header length is encoded in the top 4 bits of the tcpoffset
|
||||
* field (in units of 32-bit words).
|
||||
*/
|
||||
|
||||
sum = chksum(sum, (FAR uint8_t *)&ipv6tcp->tcp, TCP_HDRLEN);
|
||||
tcplen = ((uint16_t)ipv6tcp->tcp.tcpoffset >> 4) << 2;
|
||||
sum = chksum(sum, (FAR uint8_t *)&ipv6tcp->tcp, tcplen);
|
||||
|
||||
/* Sum payload data. */
|
||||
|
||||
|
|
@ -327,7 +333,8 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||
timeout = 0;
|
||||
#endif
|
||||
|
||||
ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6tcp,
|
||||
ret = sixlowpan_send(dev, &conn->list,
|
||||
(FAR const struct ipv6_hdr_s *)&ipv6tcp,
|
||||
buf, buflen, &destmac, timeout);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
@ -382,38 +389,62 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
|
|||
|
||||
if (dev != NULL && dev->d_len > 0)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6hdr;
|
||||
FAR struct ipv6tcp_hdr_s *ipv6hdr;
|
||||
|
||||
/* The IPv6 header followed by a TCP headers should lie at the
|
||||
* beginning of d_buf since there is no link layer protocol header
|
||||
* and the TCP state machine should only response with TCP packets.
|
||||
*/
|
||||
|
||||
ipv6hdr = (FAR struct ipv6_hdr_s *)(dev->d_buf);
|
||||
ipv6hdr = (FAR struct ipv6tcp_hdr_s *)(dev->d_buf);
|
||||
|
||||
/* The TCP data payload should follow the IPv6 header plus the
|
||||
* protocol header.
|
||||
*/
|
||||
|
||||
if (ipv6hdr->proto != IP_PROTO_TCP)
|
||||
if (ipv6hdr->ipv6.proto != IP_PROTO_TCP)
|
||||
{
|
||||
nwarn("WARNING: Expected TCP protoype: %u\n", ipv6hdr->proto);
|
||||
nwarn("WARNING: Expected TCP protoype: %u vs %s\n",
|
||||
ipv6hdr->ipv6.proto, IP_PROTO_TCP);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct rimeaddr_s destmac;
|
||||
FAR uint8_t *buf;
|
||||
uint16_t hdrlen;
|
||||
uint16_t buflen;
|
||||
|
||||
/* Get the Rime MAC address of the destination. This assumes an
|
||||
* encoding of the MAC address in the IPv6 address.
|
||||
*/
|
||||
|
||||
sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac);
|
||||
sixlowpan_rimefromip(ipv6hdr->ipv6.destipaddr, &destmac);
|
||||
|
||||
/* Convert the outgoing packet into a frame list. */
|
||||
/* Get the IPv6 + TCP combined header length. The size of the TCP
|
||||
* header is encoded in the top 4 bits of the tcpoffset field (in
|
||||
* units of 32-bit words).
|
||||
*/
|
||||
|
||||
(void)sixlowpan_queue_frames(
|
||||
(FAR struct ieee802154_driver_s *)dev, ipv6hdr,
|
||||
dev->d_buf, dev->d_len, &destmac);
|
||||
hdrlen = IPv6_HDRLEN + (((uint16_t)ipv6hdr->tcp.tcpoffset >> 4) << 2);
|
||||
|
||||
/* Drop the packet if the buffer length is less than this. */
|
||||
|
||||
if (hdrlen > dev->d_len)
|
||||
{
|
||||
nwarn("WARNING: Dropping small TCP packet: %u < %u\n",
|
||||
buflen, hdrlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert the outgoing packet into a frame list. */
|
||||
|
||||
buf = dev->d_buf + hdrlen;
|
||||
buflen = dev->d_len - hdrlen;
|
||||
|
||||
(void)sixlowpan_queue_frames(
|
||||
(FAR struct ieee802154_driver_s *)dev, &ipv6hdr->ipv6,
|
||||
buf, buflen, &destmac);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,8 +191,9 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
|
|||
|
||||
if (to6->sin6_family != AF_INET6 || tolen < sizeof(struct sockaddr_in6))
|
||||
{
|
||||
nerr("ERROR: Invalid destination address\n");
|
||||
return (ssize_t)-EAFNOSUPPORT;
|
||||
nerr("ERROR: Invalid destination address: sin6_family=%u tolen = %u\n",
|
||||
to6->sin6_family, tolen);
|
||||
return (ssize_t)-EPROTOTYPE;
|
||||
}
|
||||
|
||||
/* Get the underlying UDP "connection" structure */
|
||||
|
|
@ -200,14 +201,6 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
|
|||
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
||||
DEBUGASSERT(conn != NULL);
|
||||
|
||||
/* Ignore if not IPv6 domain */
|
||||
|
||||
if (conn->domain != PF_INET6)
|
||||
{
|
||||
nwarn("WARNING: Not IPv6\n");
|
||||
return (ssize_t)-EPROTOTYPE;
|
||||
}
|
||||
|
||||
/* Route outgoing message to the correct device */
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
|
|
@ -264,8 +257,8 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
|
|||
|
||||
/* Copy the source and destination addresses */
|
||||
|
||||
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, to6->sin6_addr.in6_u.u6_addr16);
|
||||
net_ipv6addr_hdrcopy(ipv6udp.ipv6.destipaddr, conn->u.ipv6.raddr);
|
||||
net_ipv6addr_hdrcopy(ipv6udp.ipv6.destipaddr, to6->sin6_addr.in6_u.u6_addr16);
|
||||
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, conn->u.ipv6.laddr);
|
||||
|
||||
ninfo("IPv6 length: %d\n",
|
||||
((int)ipv6udp.ipv6.len[0] << 8) + ipv6udp.ipv6.len[1]);
|
||||
|
|
@ -315,7 +308,8 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
|
|||
timeout = 0;
|
||||
#endif
|
||||
|
||||
ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6udp,
|
||||
ret = sixlowpan_send(dev, &conn->list,
|
||||
(FAR const struct ipv6_hdr_s *)&ipv6udp,
|
||||
buf, buflen, &destmac, timeout);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -185,23 +185,25 @@ static int lo_txpoll(FAR struct net_driver_s *dev)
|
|||
/* Find the tail of the IOB queue */
|
||||
|
||||
for (tail = NULL, iob = head;
|
||||
iob != NULL;
|
||||
tail = iob, iob = iob->io_flink);
|
||||
iob != NULL;
|
||||
tail = iob, iob = iob->io_flink);
|
||||
|
||||
/* Loop while there frames to be sent, i.e., while the IOB list is not
|
||||
* emtpy. Sending, of course, just means relaying back through the network
|
||||
* for this driver.
|
||||
*/
|
||||
|
||||
while (!FRAME_IOB_EMPTY(&priv->lo_ieee))
|
||||
while (head != NULL)
|
||||
{
|
||||
/* Remove the IOB from the queue */
|
||||
|
||||
FRAME_IOB_REMOVE(&priv->lo_ieee, iob);
|
||||
iob = head;
|
||||
head = iob->io_flink;
|
||||
iob->io_flink = NULL;
|
||||
|
||||
/* Is the queue now empty? */
|
||||
|
||||
if (FRAME_IOB_EMPTY(&priv->lo_ieee))
|
||||
if (head == NULL)
|
||||
{
|
||||
tail = NULL;
|
||||
}
|
||||
|
|
@ -239,8 +241,8 @@ static int lo_txpoll(FAR struct net_driver_s *dev)
|
|||
/* Find the new tail of the IOB queue */
|
||||
|
||||
for (tail = iob, iob = iob->io_flink;
|
||||
iob != NULL;
|
||||
tail = iob, iob = iob->io_flink);
|
||||
iob != NULL;
|
||||
tail = iob, iob = iob->io_flink);
|
||||
}
|
||||
|
||||
priv->lo_txdone = true;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue