Merge branch 'ieee802154'

This commit is contained in:
Gregory Nutt 2017-06-18 15:27:29 -06:00
commit 58c85705c0
21 changed files with 569 additions and 119 deletions

21
TODO
View File

@ -1234,14 +1234,14 @@ o Network (net/, drivers/net)
Title: ICMPv6 FOR 6loWPAN
Description: The current ICMPv6 and neighbor-related logic only works with
Ethernet MAC. For 6loWPAN, a new more conservative ICMPv6
definitions is provided by RFC 6775. This RFC needs to be
supported in order to support ping6 on a 6loWPAN network.
Ethernet MAC. For 6loWPAN, a new more conservative IPv6
neigbor discovery is provided by RFC 6775. This RFC needs to
be supported in order to support ping6 on a 6loWPAN network.
If RFC 6775 were implemented, then arbitrary IPv6 addresses,
including addresses from DHCPv6 could be used.
can
UPDATE: With ICMPv6 neighbor discovery, any IPv6 address may
UPDATE: With IPv6 neighbor discovery, any IPv6 address may
be associated with any short or extended address. In fact,
that is the whole purpose of the neighbor discover logic: It
plays the same role as ARP in IPv4; it ultimately just manages
@ -1256,15 +1256,18 @@ o Network (net/, drivers/net)
Most of the 6loWPAN compression algorithms exploit this to
compress the IPv6 address to nothing but a bit indicating
that the IP address derives from the node address. So I
think ICMPv6 is useless in the current implementation.
think IPv6 neighbor discover is useless in the current
implementation.
If we want to use ICMPv6, we could dispense with the all MAC
based addressing. But if we want to retain the more compact
MAC-based addressing, then we don't need ICMPv6.
If we want to use IPv6 neighbor discovery, we could dispense
with the all MAC based addressing. But if we want to retain
the more compact MAC-based addressing, then we don't need
IPv6 neighbor discovery.
So, the full neighbor discovery logic is not currently useful,
but it would still be nice to have enough in place to support
ping6.
ping6. Full neighbor support would probably be necessary if we
wanted to route 6LoWPAN frames outside of the WPAN.
Status: Open
Priority: Low for now. I don't plan on implementing this. It would

View File

@ -365,7 +365,7 @@ Configurations
nsh> i8 /dev/ieee0 startpan
nsh> i8 acceptassoc
2. Assocate and endpoint device with the WPAN. On the endpoint
2. Assocate an endpoint device with the WPAN. On the endpoint
device:
nsh> i8 /dev/ieee0 assoc
@ -432,7 +432,7 @@ Configurations
5. Configuration instructions: Basic PAN configuration is the same as
for the ieee802154-mac configuration with the exception that after
the PAN has been configured with the i8sak utility, you must
explicity bring the network up:
explicity bring the network up on each node:
nsh> ifup wpan0

View File

@ -1137,12 +1137,14 @@ CONFIG_IOB_THROTTLE=8
CONFIG_WIRELESS=y
CONFIG_WIRELESS_IEEE802154=y
CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef
CONFIG_IEEE802154_MAC_DEV=y
CONFIG_MAC802154_HPWORK=y
CONFIG_IEEE802154_NTXDESC=3
CONFIG_IEEE802154_IND_PREALLOC=20
CONFIG_IEEE802154_IND_IRQRESERVE=10
CONFIG_IEEE802154_MACDEV=y
CONFIG_IEEE802154_MACDEV_RECVRPRIO=0
CONFIG_IEEE802154_NETDEV=y
CONFIG_IEEE802154_NETDEV_RECVRPRIO=1
CONFIG_IEEE802154_NETDEV_HPWORK=y
# CONFIG_IEEE802154_LOOPBACK is not set
@ -1448,7 +1450,7 @@ CONFIG_NSH_DISABLE_GET=y
# CONFIG_NSH_DISABLE_HELP is not set
# CONFIG_NSH_DISABLE_HEXDUMP is not set
# CONFIG_NSH_DISABLE_IFCONFIG is not set
CONFIG_NSH_DISABLE_IFUPDOWN=y
# CONFIG_NSH_DISABLE_IFUPDOWN is not set
# CONFIG_NSH_DISABLE_KILL is not set
# CONFIG_NSH_DISABLE_LOSETUP is not set
CONFIG_NSH_DISABLE_LOSMART=y

View File

@ -393,6 +393,7 @@ CONFIG_STM32_HAVE_I2C2=y
CONFIG_STM32_HAVE_I2C3=y
CONFIG_STM32_HAVE_SPI2=y
CONFIG_STM32_HAVE_SPI3=y
CONFIG_STM32_HAVE_I2S3=y
# CONFIG_STM32_HAVE_SPI4 is not set
# CONFIG_STM32_HAVE_SPI5 is not set
# CONFIG_STM32_HAVE_SPI6 is not set
@ -431,6 +432,7 @@ CONFIG_STM32_PWR=y
# CONFIG_STM32_SPI1 is not set
# CONFIG_STM32_SPI2 is not set
CONFIG_STM32_SPI3=y
# CONFIG_STM32_I2S3 is not set
CONFIG_STM32_SYSCFG=y
# CONFIG_STM32_TIM1 is not set
# CONFIG_STM32_TIM2 is not set
@ -968,6 +970,7 @@ CONFIG_MM_IOB=y
CONFIG_IOB_NBUFFERS=8
CONFIG_IOB_BUFSIZE=196
CONFIG_IOB_NCHAINS=0
CONFIG_IOB_THROTTLE=0
#
# Audio Support
@ -980,11 +983,12 @@ CONFIG_IOB_NCHAINS=0
CONFIG_WIRELESS=y
CONFIG_WIRELESS_IEEE802154=y
CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef
CONFIG_IEEE802154_MAC_DEV=y
CONFIG_MAC802154_HPWORK=y
CONFIG_IEEE802154_NTXDESC=3
CONFIG_IEEE802154_IND_PREALLOC=20
CONFIG_IEEE802154_IND_IRQRESERVE=10
CONFIG_IEEE802154_MACDEV=y
CONFIG_IEEE802154_MACDEV_RECVRPRIO=0
#
# Binary Loader
@ -1162,10 +1166,10 @@ CONFIG_BUILTIN_PROXY_STACKSIZE=1024
CONFIG_EXAMPLES_NSH=y
CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y
# CONFIG_EXAMPLES_NULL is not set
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXFFS is not set
# CONFIG_EXAMPLES_NXHELLO is not set
# CONFIG_EXAMPLES_NXIMAGE is not set
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXLINES is not set
# CONFIG_EXAMPLES_NXTERM is not set
# CONFIG_EXAMPLES_NXTEXT is not set

View File

@ -270,7 +270,7 @@ static int stm32_mrf24j40_devsetup(FAR struct stm32_priv_s *priv)
}
#endif
#ifdef CONFIG_IEEE802154_MAC_DEV
#ifdef CONFIG_IEEE802154_MACDEV
/* If want to call these APIs from userspace, you have to wrap the MAC
* interface in a character device viamac802154dev_register().
*/

View File

@ -710,11 +710,11 @@ CONFIG_IOB_THROTTLE=8
CONFIG_WIRELESS=y
CONFIG_WIRELESS_IEEE802154=y
CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef
# CONFIG_IEEE802154_MAC_DEV is not set
CONFIG_MAC802154_HPWORK=y
CONFIG_IEEE802154_NTXDESC=3
CONFIG_IEEE802154_IND_PREALLOC=20
CONFIG_IEEE802154_IND_IRQRESERVE=10
# CONFIG_IEEE802154_MACDEV is not set
# CONFIG_IEEE802154_NETDEV is not set
CONFIG_IEEE802154_LOOPBACK=y
CONFIG_IEEE802154_LOOPBACK_HPWORK=y

View File

@ -1,4 +1,35 @@
Optimal 6loWPAN Configuration
6LoWPAN Addressing
------------------
The current 6LoWPAN implementation uses only link local, MAC-based
addressing addressing (as discussed in more detail below). Thus if you know
the node addressing, then you know the IPv6 address (and vice-versa)
IPv6 Neighbor Discovery is not supported. The current ICMPv6 and neighbor-
related logic only works with Ethernet MAC. For 6LoWPAN, a
new more conservative IPv6 neigbor discovery is provided by RFC 6775 which
is not currently suppored. With IPv6 neighbor discovery, any IPv6 address
may be associated with any short or extended address. In fact, that is the
whole purpose of the neighbor discover logic: It plays the same role as ARP
in IPv4; it ultimately just manages a neighbor table that, like the arp
table, provides the mapping between IP addresses and node addresses.
The NuttX, Contiki-based 6LoWPAN implementation circumvents the need for
the neighbor discovery logic by using only MAC-based addressing, i.e., the
lower two or eight bytes of the IP address are the node address.
Most of the 6LoWPAN compression algorithms exploit this kind of addressing
to compress the IPv6 address to nothing but a single bit indicating that the
IP address derives from the node address. In this use case, IPv6 neighbor
discover is not useful: If we want to use IPv6 neighbor discovery, we could
dispense with the all MAC based addressing. But if we want to retain the
more compact MAC-based addressing, then we don't need IPv6 neighbor discovery.
However, it would still be nice to have enough in place to support ping6.
Full neighbor support would be necessary if we wanted to route 6LoWPAN frames
outside of the WPAN.
Optimal 6LoWPAN Configuration
-----------------------------
1. Link local IP addresses:

View File

@ -88,12 +88,12 @@ bool sched_addprioritized(FAR struct tcb_s *tcb, DSEG dq_queue_t *list)
ASSERT(sched_priority >= SCHED_PRIORITY_MIN);
/* Search the list to find the location to insert the new Tcb.
* Each is list is maintained in ascending sched_priority order.
* Each is list is maintained in descending sched_priority order.
*/
for (next = (FAR struct tcb_s *)list->head;
(next && sched_priority <= next->sched_priority);
next = next->flink);
next = next->flink);
/* Add the tcb to the spot found in the list. Check if the tcb
* goes at the end of the list. NOTE: This could only happen if list

View File

@ -21,14 +21,6 @@ config IEEE802154_DEFAULT_EADDR
---help---
Set the default extended address to be used by MAC networks on init
config IEEE802154_MAC_DEV
bool "Character driver for IEEE 802.15.4 MAC layer"
default n
depends on WIRELESS_IEEE802154
---help---
Enable the device driver to expose the IEEE 802.15.4 MAC layer
access to user space as IOCTLs
choice
prompt "IEEE 802.15.4 work queue"
default MAC802154_LPWORK if SCHED_LPWORK
@ -83,6 +75,36 @@ config IEEE802154_IND_IRQRESERVE
Non-interrupt logic will also first attempt to allocate from the
general, pre-allocated structure pool. If that fails, it will
dynamically allocate the meta data structure with an additional cost in performance.
config IEEE802154_MACDEV
bool "Character driver for IEEE 802.15.4 MAC layer"
default n
depends on WIRELESS_IEEE802154
---help---
Enable the device driver to expose the IEEE 802.15.4 MAC layer
access to user space as IOCTLs
if IEEE802154_MACDEV
config IEEE802154_MACDEV_RECVRPRIO
int "Priority of frame receiver registerd with the MAC layer"
default 0
---help---
When the MAC layer receives an incoming data frame, it passes the frame
to registered receivers, in order of receiver priority, until one of the
receivers claim the frame.
An example case would be when 6LoWPAN and the MAC character driver are
enabled. Both have receivers registered with the MAC. The 6LoWPAN layer
should get assigned a higher priority than the character driver. In this
case, the 6LoWPAN receiver will receive the frame first. If the frame is
a 6LoWPAN frame, it will claim the frame and the MAC will not pass the
frame to any additional receivers. If it does not claim the frame, the
MAC layer will call the next highest priority receiver, in this case,
the MAC character driver (which should always be lowest priority since
it is a "catch-all" type receiver).
endif # IEEE802154_MACDEV
config IEEE802154_NETDEV
bool "IEEE802154 6loWPAN Network Device"
@ -95,6 +117,24 @@ config IEEE802154_NETDEV
if IEEE802154_NETDEV
config IEEE802154_NETDEV_RECVRPRIO
int "Priority of frame receiver registerd with the MAC layer"
default 1
---help---
When the MAC layer receives an incoming data frame, it passes the frame
to registered receivers, in order of receiver priority, until one of the
receivers claim the frame.
An example case would be when 6LoWPAN and the MAC character driver are
enabled. Both have receivers registered with the MAC. The 6LoWPAN layer
should get assigned a higher priority than the character driver. In this
case, the 6LoWPAN receiver will receive the frame first. If the frame is
a 6LoWPAN frame, it will claim the frame and the MAC will not pass the
frame to any additional receivers. If it does not claim the frame, the
MAC layer will call the next highest priority receiver, in this case,
the MAC character driver (which should always be lowest priority since
it is a "catch-all" type receiver).
choice
prompt "Work queue"
default IEEE802154_NETDEV_LPWORK if SCHED_LPWORK

View File

@ -46,7 +46,7 @@ CSRCS += mac802154_sync.c
# Include wireless devices build support
ifeq ($(CONFIG_IEEE802154_MAC_DEV),y)
ifeq ($(CONFIG_IEEE802154_MACDEV),y)
CSRCS += mac802154_device.c
endif

View File

@ -628,11 +628,13 @@ static void mac802154_txdone_worker(FAR void *arg)
notif->notiftype = IEEE802154_NOTIFY_CONF_DATA;
/* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem);
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false);
}
break;
case IEEE802154_FRAME_COMMAND:
{
switch (priv->curr_cmd)
@ -640,10 +642,13 @@ static void mac802154_txdone_worker(FAR void *arg)
case IEEE802154_CMD_ASSOC_REQ:
mac802154_txdone_assocreq(priv, txdesc);
break;
case IEEE802154_CMD_ASSOC_RESP:
break;
case IEEE802154_CMD_DISASSOC_NOT:
break;
case IEEE802154_CMD_DATA_REQ:
/* Data requests can be sent for 3 different reasons.
*
@ -663,23 +668,31 @@ static void mac802154_txdone_worker(FAR void *arg)
case MAC802154_OP_ASSOC:
mac802154_txdone_datareq_assoc(priv, txdesc);
break;
case MAC802154_OP_POLL:
mac802154_txdone_datareq_poll(priv, txdesc);
break;
default:
break;
}
break;
case IEEE802154_CMD_PANID_CONF_NOT:
break;
case IEEE802154_CMD_ORPHAN_NOT:
break;
case IEEE802154_CMD_BEACON_REQ:
break;
case IEEE802154_CMD_COORD_REALIGN:
break;
case IEEE802154_CMD_GTS_REQ:
break;
default:
/* We can deallocate the data conf notification as it is no
* longer needed. We can't use the public function here
@ -688,10 +701,12 @@ static void mac802154_txdone_worker(FAR void *arg)
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
priv->nnotif = 0;
break;
}
}
break;
default:
{
/* We can deallocate the data conf notification as it is no longer
@ -907,22 +922,30 @@ static void mac802154_rxframe_worker(FAR void *arg)
case IEEE802154_CMD_ASSOC_REQ:
mac802154_rx_assocreq(priv, ind);
break;
case IEEE802154_CMD_ASSOC_RESP:
mac802154_rx_assocresp(priv, ind);
break;
case IEEE802154_CMD_DISASSOC_NOT:
break;
case IEEE802154_CMD_DATA_REQ:
mac802154_rx_datareq(priv, ind);
break;
case IEEE802154_CMD_PANID_CONF_NOT:
break;
case IEEE802154_CMD_ORPHAN_NOT:
break;
case IEEE802154_CMD_BEACON_REQ:
break;
case IEEE802154_CMD_COORD_REALIGN:
break;
case IEEE802154_CMD_GTS_REQ:
break;
}
@ -1096,8 +1119,7 @@ static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC */
mac802154_givesem(&priv->exclsem);
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
/* If there was data, pass it along */
@ -1108,26 +1130,48 @@ static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv,
}
else
{
FAR struct mac802154_maccb_s *cb;
notify_with_lock:
mac802154_givesem(&priv->exclsem);
notify_without_lock:
/* If there is a registered MCPS callback receiver registered,
* send the frame, otherwise, throw it out.
/* If there are registered MCPS callback receivers registered,
* then forward the frame in priority order. If there are no
* registered receivers or if none of the receivers accept the
* data frame then drop the frame.
*/
if (priv->cb->rxframe != NULL)
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
priv->cb->rxframe(priv->cb, ind);
}
else
{
/* Free the data indication struct from the pool */
int ret;
ieee802154_ind_free(ind);
/* Does this MAC client want frames? */
if (cb->rxframe != NULL)
{
/* Yes.. Offer this frame to the receiver */
ret = cb->rxframe(cb, ind);
if (ret >= 0)
{
/* The receiver accepted and disposed of the frame and
* its metadata. We are done.
*/
return;
}
}
}
/* We get here if the there are no registered receivers or if
* all of the registered receivers declined the frame.
* Free the data indication struct from the pool
*/
ieee802154_ind_free(ind);
}
}

View File

@ -58,18 +58,22 @@
* Public Data Types
****************************************************************************/
/* Callback operations to notify the next highest layer of various asynchronous
* events, usually triggered by some previous request or response invoked by the
* upper layer.
/* Callback operations to notify the next highest layer of various
* asynchronous events, usually triggered by some previous request or
* response invoked by the upper layer.
*/
struct mac802154_maccb_s
{
CODE void (*notify)(FAR const struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
FAR struct mac802154_maccb_s *flink; /* Implements a singly linked list */
uint8_t prio; /* RX frame callback priority */
CODE void (*rxframe)(FAR const struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
/* Callback methods */
CODE void (*notify)(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
CODE int (*rxframe)(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
};
/****************************************************************************
@ -93,7 +97,7 @@ struct iob_s; /* Forward reference */
*
****************************************************************************/
int mac802154_bind(MACHANDLE mac, FAR const struct mac802154_maccb_s *cb);
int mac802154_bind(MACHANDLE mac, FAR struct mac802154_maccb_s *cb);
/****************************************************************************
* Name: mac802154_ioctl

View File

@ -480,7 +480,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem);
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false);
}
else
@ -612,7 +612,7 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem);
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false);
}
else
@ -708,8 +708,7 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Notify the next highest layer of the association status */
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
return;
errout_with_sem:
@ -804,7 +803,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
/* Notify the next highest layer of the association status */
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
}
/****************************************************************************
@ -853,5 +852,5 @@ static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv)
notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA;
notif->u.assocconf.saddr = IEEE802154_SADDR_UNSPEC;
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
}

View File

@ -69,12 +69,48 @@
*
****************************************************************************/
int mac802154_bind(MACHANDLE mac, FAR const struct mac802154_maccb_s *cb)
int mac802154_bind(MACHANDLE mac, FAR struct mac802154_maccb_s *cb)
{
FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac;
FAR struct mac802154_maccb_s *next;
FAR struct mac802154_maccb_s *prev;
/* Add the MAC client callback structure to the list of MAC callbacks in
* priority order.
*
* Search the list to find the location to insert the new instance.
* The list is maintained in descending priority order.
*/
for (prev = NULL, next = priv->cb;
(next != NULL && cb->prio <= next->prio);
prev = next, next = next->flink);
/* Add the instance to the spot found in the list. Check if the instance
* goes at the head of the list.
*/
if (prev == NULL)
{
cb->flink = priv->cb; /* May be NULL */
priv->cb = cb;
}
/* No.. the instance goes between prev and next */
else
{
cb->flink = next; /* May be NULL */
prev->flink = cb;
}
/* Keep track of the number of clients requesting notification */
if (cb->notify != NULL)
{
priv->nclients++;
}
priv->cb = cb;
return OK;
}

View File

@ -141,10 +141,9 @@ static inline void mac802154dev_pushevent(FAR struct mac802154_chardevice_s *dev
static inline FAR struct ieee802154_notif_s *
mac802154dev_popevent(FAR struct mac802154_chardevice_s *dev);
static void mac802154dev_notify(FAR const struct mac802154_maccb_s *maccb,
static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
static void mac802154dev_rxframe(FAR const struct mac802154_maccb_s *maccb,
static int mac802154dev_rxframe(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
static int mac802154dev_open(FAR struct file *filep);
@ -762,7 +761,7 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd,
return ret;
}
static void mac802154dev_notify(FAR const struct mac802154_maccb_s *maccb,
static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif)
{
FAR struct mac802154dev_callback_s *cb =
@ -826,8 +825,20 @@ static void mac802154dev_notify(FAR const struct mac802154_maccb_s *maccb,
mac802154dev_givesem(&dev->md_exclsem);
}
static void mac802154dev_rxframe(FAR const struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind)
/****************************************************************************
* Name: mac802154dev_rxframe
*
* Description:
* Handle received frames forward by the IEEE 802.15.4 MAC.
*
* Returned Value:
* any failure. On success, the ind and its contained iob will be freed.
* The ind will be intact if this function returns a failure.
*
****************************************************************************/
static int mac802154dev_rxframe(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct mac802154dev_callback_s *cb =
(FAR struct mac802154dev_callback_s *)maccb;
@ -858,6 +869,7 @@ static void mac802154dev_rxframe(FAR const struct mac802154_maccb_s *maccb,
/* Release the driver */
mac802154dev_givesem(&dev->md_exclsem);
return OK;
}
/****************************************************************************
@ -923,6 +935,8 @@ int mac802154dev_register(MACHANDLE mac, int minor)
dev->md_cb.mc_priv = dev;
maccb = &dev->md_cb.mc_cb;
maccb->flink = NULL;
maccb->prio = CONFIG_IEEE802154_MACDEV_RECVRPRIO;
maccb->notify = mac802154dev_notify;
maccb->rxframe = mac802154dev_rxframe;

View File

@ -147,10 +147,12 @@ typedef void (*mac802154_worker_t)(FAR struct ieee802154_privmac_s *priv);
struct ieee802154_privmac_s
{
FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */
FAR const struct mac802154_maccb_s *cb; /* Contained MAC callbacks */
FAR struct mac802154_maccb_s *cb; /* Head of a list of MAC callbacks */
FAR struct mac802154_radiocb_s radiocb; /* Interface to bind to radio */
sem_t exclsem; /* Support exclusive access */
sem_t exclsem; /* Support exclusive access */
uint8_t nclients; /* Number of notification clients */
uint8_t nnotif; /* Number of remaining notifications */
/* Only support a single command at any given time. As of now I see no
* condition where you need to have more than one command frame simultaneously

View File

@ -128,9 +128,10 @@ static uint16_t g_panid = 0xcafe;
* Private Function Prototypes
****************************************************************************/
/* IP address conversion */
/* Utility functions */
static void lo_addr2ip(FAR struct net_driver_s *dev);
static inline void lo_netmask(FAR struct net_driver_s *dev);
/* Polling logic */
@ -170,7 +171,7 @@ static int lo_req_data(FAR struct ieee802154_driver_s *netdev,
*
* Description:
* Create a MAC-based IP address from the IEEE 802.15.14 short or extended
* address of the MAC.
* address assigned to the node.
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
@ -189,8 +190,8 @@ static void lo_addr2ip(FAR struct net_driver_s *dev)
dev->d_ipv6addr[4] = (uint16_t)g_eaddr[0] << 8 | (uint16_t)g_eaddr[1];
dev->d_ipv6addr[5] = (uint16_t)g_eaddr[2] << 8 | (uint16_t)g_eaddr[3];
dev->d_ipv6addr[6] = (uint16_t)g_eaddr[4] << 8 | (uint16_t)g_eaddr[5];
dev->d_ipv6addr[6] = (uint16_t)g_eaddr[6] << 8 | (uint16_t)g_eaddr[6];
dev->d_ipv6addr[6] ^= 0x200;
dev->d_ipv6addr[7] = (uint16_t)g_eaddr[6] << 8 | (uint16_t)g_eaddr[6];
dev->d_ipv6addr[4] ^= 0x200;
}
#else
static void lo_addr2ip(FAR struct net_driver_s *dev)
@ -201,12 +202,45 @@ static void lo_addr2ip(FAR struct net_driver_s *dev)
dev->d_ipv6addr[3] = 0;
dev->d_ipv6addr[4] = 0;
dev->d_ipv6addr[5] = HTONS(0x00ff);
dev->d_ipv6addr[0] = HTONS(0xfe00);
dev->d_ipv6addr[0] = htons(g_saddr) ^ 0x0200;
dev->d_ipv6addr[6] ^= 0x200;
dev->d_ipv6addr[6] = HTONS(0xfe00);
dev->d_ipv6addr[7] = htons(g_saddr);
dev->d_ipv6addr[7] ^= 0x200;
}
#endif
/****************************************************************************
* Name: lo_netmask
*
* Description:
* Create a netmask of a MAC-based IP address which may be based on either
* the IEEE 802.15.14 short or extended address of the MAC.
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64
*
****************************************************************************/
static inline void lo_netmask(FAR struct net_driver_s *dev)
{
dev->d_ipv6netmask[0] = 0xffff;
dev->d_ipv6netmask[1] = 0xffff;
dev->d_ipv6netmask[2] = 0xffff;
dev->d_ipv6netmask[3] = 0xffff;
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
dev->d_ipv6netmask[4] = 0;
dev->d_ipv6netmask[5] = 0;
dev->d_ipv6netmask[6] = 0;
dev->d_ipv6netmask[7] = 0;
#else
dev->d_ipv6netmask[4] = 0xffff;
dev->d_ipv6netmask[5] = 0xffff;
dev->d_ipv6netmask[6] = 0xffff;
dev->d_ipv6netmask[7] = 0;
#endif
}
/****************************************************************************
* Name: lo_loopback
*
@ -861,8 +895,9 @@ int ieee8021514_loopback(void)
dev->d_buf = g_iobuffer; /* Attach the IO buffer */
dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */
/* Advertise our MAC-based IP address */
/* Set the network mask and advertise our MAC-based IP address */
lo_netmask(dev);
lo_addr2ip(dev);
/* Initialize the Network frame-related callbacks */

View File

@ -109,7 +109,7 @@ struct macnet_callback_s
{
/* This holds the information visible to the MAC layer */
struct mac802154_maccb_s mc_cb; /* Interface understood by the MAC layer */
struct mac802154_maccb_s mc_cb; /* Interface understood by the MAC layer */
FAR struct macnet_driver_s *mc_priv; /* Our priv data */
};
@ -136,11 +136,16 @@ struct macnet_driver_s
* Private Function Prototypes
****************************************************************************/
/* Utility functions ********************************************************/
static int macnet_advertise(FAR struct net_driver_s *dev);
static inline void macnet_netmask(FAR struct net_driver_s *dev);
/* IEE802.15.4 MAC callback functions ***************************************/
static void macnet_notify(FAR const struct mac802154_maccb_s *maccb,
static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb,
static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
/* Asynchronous confirmations to requests */
@ -162,7 +167,7 @@ static void macnet_conf_start(FAR struct macnet_driver_s *priv,
static void macnet_conf_poll(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_poll_conf_s *conf);
/* Asynchronous event indications, replied to synchronously with responses */
/* Asynchronous event indications, replied to synchronously with responses */
static void macnet_ind_associate(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_assoc_ind_s *conf);
@ -216,6 +221,133 @@ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev,
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: macnet_advertise
*
* Description:
* Advertise the MAC and IPv6 address for this node.
*
* Creates a MAC-based IP address from the IEEE 802.15.14 short or extended
* address assigned to the node.
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64
*
****************************************************************************/
static int macnet_advertise(FAR struct net_driver_s *dev)
{
struct ieee802154_netmac_s arg;
int ret;
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
uint8_t *eaddr;
/* Get the eaddr from the MAC */
memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ);
arg.u.getreq.attr = IEEE802154_ATTR_MAC_EXTENDED_ADDR;
ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)((uintptr_t)&arg));
if (ret < 0)
{
wlerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
return ret;
}
else
{
/* Set the IP address based on the eaddr */
eaddr = arg.u.getreq.attrval.mac.eaddr;
memcpy(dev->d_mac.ieee802154.u8, eaddr, 8);
dev->d_ipv6addr[0] = HTONS(0xfe80);
dev->d_ipv6addr[1] = 0;
dev->d_ipv6addr[2] = 0;
dev->d_ipv6addr[3] = 0;
dev->d_ipv6addr[4] = (uint16_t)eaddr[0] << 8 | (uint16_t)eaddr[1];
dev->d_ipv6addr[5] = (uint16_t)eaddr[2] << 8 | (uint16_t)eaddr[3];
dev->d_ipv6addr[6] = (uint16_t)eaddr[4] << 8 | (uint16_t)eaddr[5];
dev->d_ipv6addr[7] = (uint16_t)eaddr[6] << 8 | (uint16_t)eaddr[6];
dev->d_ipv6addr[4] ^= 0x200;
return OK;
}
#else
/* Get the saddr from the MAC */
memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ);
arg.u.getreq.attr = IEEE802154_ATTR_MAC_SHORT_ADDRESS;
ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)((uintptr_t)&arg));
if (ret < 0)
{
wlerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
return ret;
}
else
{
union
{
uint16_t u16;
uint8_t u8[2];
} u;
u.u16 = arg.u.getreq.attrval.mac.saddr;
dev->d_mac.ieee802154.u8[0] = u.u8[0];
dev->d_mac.ieee802154.u8[1] = u.u8[1];
/* Set the IP address based on the saddr */
dev->d_ipv6addr[0] = HTONS(0xfe80);
dev->d_ipv6addr[1] = 0;
dev->d_ipv6addr[2] = 0;
dev->d_ipv6addr[3] = 0;
dev->d_ipv6addr[4] = 0;
dev->d_ipv6addr[5] = HTONS(0x00ff);
dev->d_ipv6addr[6] = HTONS(0xfe00);
dev->d_ipv6addr[7] = u.u16;
dev->d_ipv6addr[7] ^= 0x200;
return OK;
}
#endif
}
/****************************************************************************
* Name: macnet_netmask
*
* Description:
* Create a netmask of a MAC-based IP address which may be based on either
* the IEEE 802.15.14 short or extended address of the MAC.
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64
*
****************************************************************************/
static inline void macnet_netmask(FAR struct net_driver_s *dev)
{
dev->d_ipv6netmask[0] = 0xffff;
dev->d_ipv6netmask[1] = 0xffff;
dev->d_ipv6netmask[2] = 0xffff;
dev->d_ipv6netmask[3] = 0xffff;
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
dev->d_ipv6netmask[4] = 0;
dev->d_ipv6netmask[5] = 0;
dev->d_ipv6netmask[6] = 0;
dev->d_ipv6netmask[7] = 0;
#else
dev->d_ipv6netmask[4] = 0xffff;
dev->d_ipv6netmask[5] = 0xffff;
dev->d_ipv6netmask[6] = 0xffff;
dev->d_ipv6netmask[7] = 0;
#endif
}
/****************************************************************************
* Name: macnet_notify
*
@ -223,7 +355,7 @@ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev,
*
****************************************************************************/
static void macnet_notify(FAR const struct mac802154_maccb_s *maccb,
static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif)
{
FAR struct macnet_callback_s *cb =
@ -244,17 +376,27 @@ static void macnet_notify(FAR const struct mac802154_maccb_s *maccb,
default:
break;
}
/* Free the event notification */
mac802154_notif_free(priv->md_mac, notif);
}
/****************************************************************************
* Name: macnet_rxframe
*
* Description:
* Handle received frames forward by the IEEE 802.15.4 MAC.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure. On success, the ind and its contained iob will be freed.
* The ind will be intact if this function returns a failure.
*
****************************************************************************/
static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind)
static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct macnet_callback_s *cb =
(FAR struct macnet_callback_s *)maccb;
@ -264,10 +406,31 @@ static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb,
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
priv = cb->mc_priv;
/* Extract the IOB containing the frame from the struct ieee802154_data_ind_s */
/* Ignore the frame if the network is not up */
if (!priv->md_bifup)
{
return -ENETDOWN;
}
/* Peek the IOB contained the frame in the struct ieee802154_data_ind_s */
DEBUGASSERT(priv != NULL && ind != NULL && ind->frame != NULL);
iob = ind->frame;
iob = ind->frame;
/* If the frame is not a 6LoWPAN frame, then return an error. The first
* byte following the MAC head at the io_offset should be a valid IPHC
* header.
*/
if ((iob->io_data[iob->io_offset] & SIXLOWPAN_DISPATCH_NALP_MASK) ==
SIXLOWPAN_DISPATCH_NALP)
{
return -EINVAL;
}
/* Remove the IOB containing the frame. */
ind->frame = NULL;
/* Transfer the frame to the network logic */
@ -279,6 +442,7 @@ static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb,
*/
ieee802154_ind_free(ind);
return OK;
}
/****************************************************************************
@ -624,34 +788,43 @@ static void macnet_txpoll_expiry(int argc, wdparm_t arg, ...)
static int macnet_ifup(FAR struct net_driver_s *dev)
{
FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private;
FAR struct macnet_driver_s *priv =
(FAR struct macnet_driver_s *)dev->d_private;
int ret;
#ifdef CONFIG_NET_IPv4
ninfo("Bringing up: %d.%d.%d.%d\n",
dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,
(dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
#endif
#ifdef CONFIG_NET_IPv6
ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%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]);
/* Set the IP address based on the addressing assigned to the node */
ret = macnet_advertise(dev);
if (ret >= 0)
{
ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%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]);
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
ninfo(" Node: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
dev->d_mac.ieee802154.u8[0], dev->d_mac.ieee802154.u8[1],
dev->d_mac.ieee802154.u8[2], dev->d_mac.ieee802154.u8[3],
dev->d_mac.ieee802154.u8[4], dev->d_mac.ieee802154.u8[5],
dev->d_mac.ieee802154.u8[6], dev->d_mac.ieee802154.u8[7]);
#else
ninfo(" Node: %02x:%02x\n",
dev->d_mac.ieee802154.u8[0], dev->d_mac.ieee802154.u8[1]);
#endif
/* Initialize PHYs, the IEEE 802.15.4 interface, and setup up IEEE 802.15.4 interrupts */
#warning Missing logic
/* Set and activate a timer process */
/* Setup up address filtering */
(void)wd_start(priv->md_txpoll, TXPOLL_WDDELAY, macnet_txpoll_expiry,
1, (wdparm_t)priv);
/* Set and activate a timer process */
/* The interface is now up */
(void)wd_start(priv->md_txpoll, TXPOLL_WDDELAY, macnet_txpoll_expiry, 1,
(wdparm_t)priv);
priv->md_bifup = true;
ret = OK;
}
/* Enable the IEEE 802.15.4 radio */
priv->md_bifup = true;
return OK;
return ret;
}
/****************************************************************************
@ -993,7 +1166,7 @@ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev,
*
* Description:
* Register a network driver to access the IEEE 802.15.4 MAC layer from
* a socket using 6loWPAN
* a socket using 6LoWPAN
*
* Input Parameters:
* mac - Pointer to the mac layer struct to be registered.
@ -1062,6 +1235,10 @@ int mac802154netdev_register(MACHANDLE mac)
DEBUGASSERT(priv->md_txpoll != NULL);
/* Set the network mask. */
macnet_netmask(dev);
/* Initialize the Network frame-related callbacks */
ieee->i_get_mhrlen = macnet_get_mhrlen; /* Get MAC header length */
@ -1072,6 +1249,8 @@ int mac802154netdev_register(MACHANDLE mac)
priv->md_cb.mc_priv = priv;
maccb = &priv->md_cb.mc_cb;
maccb->flink = NULL;
maccb->prio = CONFIG_IEEE802154_NETDEV_RECVRPRIO;
maccb->notify = macnet_notify;
maccb->rxframe = macnet_rxframe;

View File

@ -74,18 +74,38 @@ int mac802154_notif_free(MACHANDLE mac,
{
FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac;
FAR struct mac802154_notif_s *privnotif = (FAR struct mac802154_notif_s *)notif;
FAR struct mac802154_notif_s *privnotif =
(FAR struct mac802154_notif_s *)notif;
/* Get exclusive access to the MAC */
mac802154_takesem(&priv->exclsem, false);
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
mac802154_givesem(&priv->notif_sem);
/* We know how many clients have registered for notifications. Each must
* call mac802154_notif_free() before we can release the notification
* resource.
*/
if (priv->nnotif < 2)
{
/* This is the free from the last notification */
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
priv->nnotif = 0;
mac802154_givesem(&priv->notif_sem);
}
else
{
/* More calls are expected. Decrement the count of expected calls
* and preserve the notification resources.
*/
priv->nnotif--;
}
mac802154_givesem(&priv->exclsem);
return -ENOTTY;
}
@ -125,6 +145,7 @@ void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv)
pool++;
remaining--;
}
sem_init(&priv->notif_sem, 0, CONFIG_MAC802154_NNOTIF);
}
@ -165,6 +186,7 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
{
privnotif = priv->notif_free;
priv->notif_free = privnotif->flink;
priv->nnotif = 0;
}
else
{
@ -200,9 +222,44 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
privnotif = priv->notif_free;
priv->notif_free = privnotif->flink;
priv->nnotif = 0;
}
*notif = (FAR struct ieee802154_notif_s *)privnotif;
return OK;
}
}
/****************************************************************************
* Name: mac802154_notify
*
* Description:
* Notify every register MAC client.
*
****************************************************************************/
void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct mac802154_maccb_s *cb;
/* Set the notification count so that the notification resources will be
* preserved until the final notification.
*/
priv->nnotif = priv->nclients;
/* Try to notify every registered MAC client */
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
/* Does this client want notifications? */
if (cb->notify != NULL)
{
/* Yes.. Notify */
cb->notify(cb, notif);
}
}
}

View File

@ -63,8 +63,8 @@
struct mac802154_notif_s
{
struct ieee802154_notif_s pub;
FAR struct mac802154_notif_s *flink;
struct ieee802154_notif_s pub; /* Publically visible structure */
FAR struct mac802154_notif_s *flink; /* Supports a singly linked list */
};
/****************************************************************************
@ -79,4 +79,7 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s **notif,
bool allow_interrupt);
void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif);
#endif /* __WIRELESS_IEEE802154__MAC802154_NOTIF_H */

View File

@ -50,8 +50,6 @@
#include <debug.h>
#include <string.h>
#include <nuttx/mm/iob.h>
#include "mac802154.h"
#include "mac802154_internal.h"
@ -83,7 +81,6 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req)
{
FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac;
FAR struct iob_s *iob;
FAR struct ieee802154_txdesc_s *txdesc;
int ret;
@ -221,7 +218,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */
mac802154_givesem(&priv->exclsem);
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
mac802154_takesem(&priv->exclsem, false);
}
else
@ -261,7 +258,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
*
****************************************************************************/
static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv)
void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv)
{
FAR struct ieee802154_notif_s *notif;
@ -286,5 +283,5 @@ static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv)
notif->notiftype = IEEE802154_NOTIFY_CONF_POLL;
notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA;
priv->cb->notify(priv->cb, notif);
mac802154_notify(priv, notif);
}