Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
NuttX RTOS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
f4grx
NuttX RTOS
Commits
04346eba
Commit
04346eba
authored
7 years ago
by
Gregory Nutt
Browse files
Options
Downloads
Patches
Plain Diff
iee802154 loopback: Eliminate dependency on CONFIG_NET_LOOPBACK
parent
e320e5c1
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
wireless/ieee802154/Kconfig
+31
-0
31 additions, 0 deletions
wireless/ieee802154/Kconfig
wireless/ieee802154/Make.defs
+6
-2
6 additions, 2 deletions
wireless/ieee802154/Make.defs
wireless/ieee802154/mac802154_loopback.c
+585
-0
585 additions, 0 deletions
wireless/ieee802154/mac802154_loopback.c
with
622 additions
and
2 deletions
wireless/ieee802154/Kconfig
+
31
−
0
View file @
04346eba
...
@@ -12,4 +12,35 @@ config WIRELESS_IEEE802154
...
@@ -12,4 +12,35 @@ config WIRELESS_IEEE802154
if IEEE802154
if IEEE802154
config IEEE802154_LOOPBACK
bool "IEEE802154 6loWPAN Loopback"
default n
depends on NET_6LOWPAN && NET_IPv6
select ARCH_HAVE_NETDEV_STATISTICS
---help---
Add support for the IEEE802154 6loWPAN Loopback test device.
if IEEE802154_LOOPBACK
choice
prompt "Work queue"
default IEEE802154_LOOPBACK_LPWORK if SCHED_LPWORK
default IEEE802154_LOOPBACK_HPWORK if !SCHED_LPWORK && SCHED_HPWORK
depends on SCHED_WORKQUEUE
---help---
Work queue support is required to use the loopback driver. If the
low priority work queue is available, then it should be used by the
loopback driver.
config IEEE802154_LOOPBACK_HPWORK
bool "High priority"
depends on SCHED_HPWORK
config IEEE802154_LOOPBACK_LPWORK
bool "Low priority"
depends on SCHED_LPWORK
endchoice # Work queue
endif # IEEE802154_LOOPBACK
endif # IEEE802154
endif # IEEE802154
This diff is collapsed.
Click to expand it.
wireless/ieee802154/Make.defs
+
6
−
2
View file @
04346eba
...
@@ -39,8 +39,12 @@ ifeq ($(CONFIG_WIRELESS_IEEE802154),y)
...
@@ -39,8 +39,12 @@ ifeq ($(CONFIG_WIRELESS_IEEE802154),y)
# Include wireless devices build support
# Include wireless devices build support
DEPPATH += --dep-path wireless/ieee802154
ifeq ($(CONFIG_IEEE802154_LOOPBACK),y)
VPATH += :wireless/ieee802154
CSRCS += mac802154_loopback.c
endif
DEPPATH += --dep-path ieee802154
VPATH += :ieee802154
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)wireless$(DELIM)ieee802154}
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)wireless$(DELIM)ieee802154}
endif # CONFIG_WIRELESS_IEEE802154
endif # CONFIG_WIRELESS_IEEE802154
This diff is collapsed.
Click to expand it.
wireless/ieee802154/mac802154_loopback.c
0 → 100644
+
585
−
0
View file @
04346eba
/****************************************************************************
* wireless/iee802154/mac802154_loopback.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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
<stdbool.h>
#include
<string.h>
#include
<errno.h>
#include
<assert.h>
#include
<debug.h>
#include
<arpa/inet.h>
#include
<net/if.h>
#include
<nuttx/wdog.h>
#include
<nuttx/wqueue.h>
#include
<nuttx/net/net.h>
#include
<nuttx/net/ip.h>
#include
<nuttx/net/loopback.h>
#ifndef CONFIG_NET_LOOPBACK
# include <nuttx/net/sixlowpan.h>
#endif
#ifdef CONFIG_IEEE802154_LOOPBACK
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* We need to have the work queue to handle SPI interrupts */
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Worker thread support is required (CONFIG_SCHED_WORKQUEUE)
#else
# if defined(CONFIG_IEEE802154_LOOPBACK_HPWORK)
# define LPBKWORK HPWORK
# elif defined(CONFIG_IEEE802154_LOOPBACK_LPWORK)
# define LPBKWORK LPWORK
# else
# error Neither CONFIG_IEEE802154_LOOPBACK_HPWORK nor CONFIG_IEEE802154_LOOPBACK_LPWORK defined
# endif
#endif
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */
#define LO_WDDELAY (1*CLK_TCK)
/****************************************************************************
* Private Types
****************************************************************************/
/* The lo_driver_s encapsulates all state information for a single hardware
* interface
*/
struct
lo_driver_s
{
bool
lo_bifup
;
/* true:ifup false:ifdown */
bool
lo_txdone
;
/* One RX packet was looped back */
WDOG_ID
lo_polldog
;
/* TX poll timer */
struct
work_s
lo_work
;
/* For deferring poll work to the work queue */
/* This holds the information visible to the NuttX network */
struct
ieee802154_driver_s
lo_ieee
;
/* Interface understood by the network */
};
/****************************************************************************
* Private Data
****************************************************************************/
static
struct
lo_driver_s
g_loopback
;
static
uint8_t
g_iobuffer
[
CONFIG_NET_6LOWPAN_MTU
+
CONFIG_NET_GUARDSIZE
];
#ifndef CONFIG_NET_LOOPBACK
static
const
net_ipv6addr_t
g_lo_ipv6addr
=
{
HTONS
(
0
),
HTONS
(
0
),
HTONS
(
0
),
HTONS
(
0
),
HTONS
(
0
),
HTONS
(
0
),
HTONS
(
0
),
HTONS
(
1
)
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Polling logic */
static
int
lo_txpoll
(
FAR
struct
net_driver_s
*
dev
);
static
void
lo_poll_work
(
FAR
void
*
arg
);
static
void
lo_poll_expiry
(
int
argc
,
wdparm_t
arg
,
...);
/* NuttX callback functions */
static
int
lo_ifup
(
FAR
struct
net_driver_s
*
dev
);
static
int
lo_ifdown
(
FAR
struct
net_driver_s
*
dev
);
static
void
lo_txavail_work
(
FAR
void
*
arg
);
static
int
lo_txavail
(
FAR
struct
net_driver_s
*
dev
);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static
int
lo_addmac
(
FAR
struct
net_driver_s
*
dev
,
FAR
const
uint8_t
*
mac
);
#ifdef CONFIG_NET_IGMP
static
int
lo_rmmac
(
FAR
struct
net_driver_s
*
dev
,
FAR
const
uint8_t
*
mac
);
#endif
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Function: lo_txpoll
*
* Description:
* Check if the network has any outgoing packets ready to send. This is
* a callback from devif_poll() or devif_timer(). devif_poll() will be
* called only during normal TX polling.
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* OK on success; a negated errno on failure
*
* Assumptions:
* May or may not be called from an interrupt handler. In either case,
* the network is locked.
*
****************************************************************************/
static
int
lo_txpoll
(
FAR
struct
net_driver_s
*
dev
)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
dev
->
d_private
;
FAR
struct
iob_s
*
head
;
FAR
struct
iob_s
*
tail
;
FAR
struct
iob_s
*
iob
;
int
ret
;
/* Remove the queued IOBs from driver structure */
head
=
priv
->
lo_ieee
.
i_framelist
;
/* Find the tail of the IOB queue */
for
(
tail
=
NULL
,
iob
=
head
;
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
))
{
/* Remove the IOB from the queue */
FRAME_IOB_REMOVE
(
&
priv
->
lo_ieee
,
iob
);
/* Is the queue now empty? */
if
(
FRAME_IOB_EMPTY
(
&
priv
->
lo_ieee
))
{
tail
=
NULL
;
}
/* Return the next frame to the network */
iob
->
io_flink
=
NULL
;
priv
->
lo_ieee
.
i_framelist
=
iob
;
ninfo
(
"Send frame %p to the network. Length=%u
\n
"
,
iob
,
iob
->
io_len
);
ret
=
sixlowpan_input
(
&
priv
->
lo_ieee
);
if
(
ret
<
0
)
{
nerr
(
"ERROR: sixlowpan_input returned %d
\n
"
,
ret
);
}
/* What if the network responds with more frames to send? */
if
(
priv
->
lo_ieee
.
i_framelist
!=
NULL
)
{
/* Append the new list to the tail of the queue */
iob
=
priv
->
lo_ieee
.
i_framelist
;
priv
->
lo_ieee
.
i_framelist
=
NULL
;
if
(
tail
==
NULL
)
{
head
=
iob
;
}
else
{
tail
->
io_flink
=
iob
;
}
/* Find the new tail of the IOB queue */
for
(
tail
=
iob
,
iob
=
iob
->
io_flink
;
iob
!=
NULL
;
tail
=
iob
,
iob
=
iob
->
io_flink
);
}
priv
->
lo_txdone
=
true
;
}
return
0
;
}
/****************************************************************************
* Function: lo_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked
*
****************************************************************************/
static
void
lo_poll_work
(
FAR
void
*
arg
)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
arg
;
/* Perform the poll */
net_lock
();
priv
->
lo_txdone
=
false
;
(
void
)
devif_timer
(
&
priv
->
lo_ieee
.
i_dev
,
lo_txpoll
);
/* Was something received and looped back? */
while
(
priv
->
lo_txdone
)
{
/* Yes, poll again for more TX data */
priv
->
lo_txdone
=
false
;
(
void
)
devif_poll
(
&
priv
->
lo_ieee
.
i_dev
,
lo_txpoll
);
}
/* Setup the watchdog poll timer again */
(
void
)
wd_start
(
priv
->
lo_polldog
,
LO_WDDELAY
,
lo_poll_expiry
,
1
,
priv
);
net_unlock
();
}
/****************************************************************************
* Function: lo_poll_expiry
*
* Description:
* Periodic timer handler. Called from the timer interrupt handler.
*
* Parameters:
* argc - The number of available arguments
* arg - The first argument
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static
void
lo_poll_expiry
(
int
argc
,
wdparm_t
arg
,
...)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
arg
;
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue
(
LPBKWORK
,
&
priv
->
lo_work
,
lo_poll_work
,
priv
,
0
);
}
/****************************************************************************
* Function: lo_ifup
*
* Description:
* NuttX Callback: Bring up the Ethernet interface when an IP address is
* provided
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static
int
lo_ifup
(
FAR
struct
net_driver_s
*
dev
)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
dev
->
d_private
;
#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2
ninfo
(
"Bringing up: Rime %02x:%02x PANID=%04x
\n
"
,
dev
->
d_ipv6addr
[
0
],
dev
->
d_ipv6addr
[
1
],
priv
->
lo_ieee
.
i_panid
);
#elif CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 8
ninfo
(
"Bringing up: Rime %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x PANID=%04x
\n
"
,
dev
->
d_ipv6addr
[
0
],
dev
->
d_ipv6addr
[
1
],
dev
->
d_ipv6addr
[
2
],
dev
->
d_ipv6addr
[
3
],
dev
->
d_ipv6addr
[
4
],
dev
->
d_ipv6addr
[
5
],
dev
->
d_ipv6addr
[
6
],
dev
->
d_ipv6addr
[
7
],
priv
->
lo_ieee
.
i_panid
);
#endif
/* Set and activate a timer process */
(
void
)
wd_start
(
priv
->
lo_polldog
,
LO_WDDELAY
,
lo_poll_expiry
,
1
,
(
wdparm_t
)
priv
);
priv
->
lo_bifup
=
true
;
return
OK
;
}
/****************************************************************************
* Function: lo_ifdown
*
* Description:
* NuttX Callback: Stop the interface.
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static
int
lo_ifdown
(
FAR
struct
net_driver_s
*
dev
)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
dev
->
d_private
;
/* Cancel the TX poll timer and TX timeout timers */
wd_cancel
(
priv
->
lo_polldog
);
/* Mark the device "down" */
priv
->
lo_bifup
=
false
;
return
OK
;
}
/****************************************************************************
* Function: lo_txavail_work
*
* Description:
* Perform an out-of-cycle poll on the worker thread.
*
* Parameters:
* arg - Reference to the NuttX driver state structure (cast to void*)
*
* Returned Value:
* None
*
* Assumptions:
* Called on the higher priority worker thread.
*
****************************************************************************/
static
void
lo_txavail_work
(
FAR
void
*
arg
)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
arg
;
/* Ignore the notification if the interface is not yet up */
net_lock
();
if
(
priv
->
lo_bifup
)
{
do
{
/* If so, then poll the network for new XMIT data */
priv
->
lo_txdone
=
false
;
(
void
)
devif_poll
(
&
priv
->
lo_ieee
.
i_dev
,
lo_txpoll
);
}
while
(
priv
->
lo_txdone
);
}
net_unlock
();
}
/****************************************************************************
* Function: lo_txavail
*
* Description:
* Driver callback invoked when new TX data is available. This is a
* stimulus perform an out-of-cycle poll and, thereby, reduce the TX
* latency.
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called in normal user mode
*
****************************************************************************/
static
int
lo_txavail
(
FAR
struct
net_driver_s
*
dev
)
{
FAR
struct
lo_driver_s
*
priv
=
(
FAR
struct
lo_driver_s
*
)
dev
->
d_private
;
/* Is our single work structure available? It may not be if there are
* pending interrupt actions and we will have to ignore the Tx
* availability action.
*/
if
(
work_available
(
&
priv
->
lo_work
))
{
/* Schedule to serialize the poll on the worker thread. */
work_queue
(
LPBKWORK
,
&
priv
->
lo_work
,
lo_txavail_work
,
priv
,
0
);
}
return
OK
;
}
/****************************************************************************
* Function: lo_addmac
*
* Description:
* NuttX Callback: Add the specified MAC address to the hardware multicast
* address filtering
*
* Parameters:
* dev - Reference to the NuttX driver state structure
* mac - The MAC address to be added
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static
int
lo_addmac
(
FAR
struct
net_driver_s
*
dev
,
FAR
const
uint8_t
*
mac
)
{
/* There is no multicast support in the loopback driver */
return
OK
;
}
#endif
/****************************************************************************
* Function: lo_rmmac
*
* Description:
* NuttX Callback: Remove the specified MAC address from the hardware multicast
* address filtering
*
* Parameters:
* dev - Reference to the NuttX driver state structure
* mac - The MAC address to be removed
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
#ifdef CONFIG_NET_IGMP
static
int
lo_rmmac
(
FAR
struct
net_driver_s
*
dev
,
FAR
const
uint8_t
*
mac
)
{
/* There is no multicast support in the loopback driver */
return
OK
;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: localhost_initialize
*
* Description:
* Initialize the Ethernet controller and driver
*
* Parameters:
* intf - In the case where there are multiple EMACs, this value
* identifies which EMAC is to be initialized.
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/
int
localhost_initialize
(
void
)
{
FAR
struct
lo_driver_s
*
priv
;
FAR
struct
net_driver_s
*
dev
;
/* Get the interface structure associated with this interface number. */
priv
=
&
g_loopback
;
/* Initialize the driver structure */
memset
(
priv
,
0
,
sizeof
(
struct
lo_driver_s
));
dev
=
&
priv
->
lo_ieee
.
i_dev
;
dev
->
d_ifup
=
lo_ifup
;
/* I/F up (new IP address) callback */
dev
->
d_ifdown
=
lo_ifdown
;
/* I/F down callback */
dev
->
d_txavail
=
lo_txavail
;
/* New TX data callback */
#ifdef CONFIG_NET_IGMP
dev
->
d_addmac
=
lo_addmac
;
/* Add multicast MAC address */
dev
->
d_rmmac
=
lo_rmmac
;
/* Remove multicast MAC address */
#endif
dev
->
d_buf
=
g_iobuffer
;
/* Attach the IO buffer */
dev
->
d_private
=
(
FAR
void
*
)
priv
;
/* Used to recover private state from dev */
/* Create a watchdog for timing polling for and timing of transmissions */
priv
->
lo_polldog
=
wd_create
();
/* Create periodic poll timer */
/* Register the loopabck device with the OS so that socket IOCTLs can b
* performed.
*/
(
void
)
netdev_register
(
&
priv
->
lo_ieee
.
i_dev
,
NET_LL_IEEE802154
);
/* Set the local loopback IP address */
net_ipv6addr_copy
(
dev
->
d_ipv6addr
,
g_lo_ipv6addr
);
net_ipv6addr_copy
(
dev
->
d_ipv6draddr
,
g_lo_ipv6addr
);
net_ipv6addr_copy
(
dev
->
d_ipv6netmask
,
g_ipv6_alloneaddr
);
/* Put the network in the UP state */
dev
->
d_flags
=
IFF_UP
;
return
lo_ifup
(
&
priv
->
lo_ieee
.
i_dev
);
}
#endif
/* CONFIG_IEEE802154_LOOPBACK */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment