IEEE 802.15.4 MAC: Add list management and prioritization logic that will permit the MAC layer to support bound multiple clients.

This commit is contained in:
Gregory Nutt 2017-06-18 11:00:47 -06:00
parent 87dd6557de
commit 2d4ba3ee3f
11 changed files with 204 additions and 50 deletions

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

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

@ -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

@ -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,8 +21,6 @@ config IEEE802154_DEFAULT_EADDR
---help---
Set the default extended address to be used by MAC networks on init
choice
prompt "IEEE 802.15.4 work queue"
default MAC802154_LPWORK if SCHED_LPWORK
@ -88,14 +86,14 @@ config IEEE802154_MACDEV
if IEEE802154_MACDEV
config IEEE802154_MACDEV_RECEIVERPRIORITY
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.
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
@ -119,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

@ -73,6 +73,11 @@
static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv);
/* MAC client notification */
static void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif);
/* IEEE 802.15.4 PHY Interface OPs */
static int mac802154_radiopoll(FAR const struct ieee802154_radiocb_s *radiocb,
@ -491,6 +496,34 @@ static void mac802154_purge_worker(FAR void *arg)
}
}
/****************************************************************************
* Name: mac802154_notify
*
* Description:
* Notify every register MAC client.
*
****************************************************************************/
static void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct mac802154_maccb_s *cb;
/* 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);
}
}
}
/****************************************************************************
* Name: mac802154_radiopoll
*
@ -628,8 +661,9 @@ 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;
@ -1096,8 +1130,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 +1141,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

@ -69,12 +69,41 @@
*
****************************************************************************/
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;
}
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,7 +147,7 @@ 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 */

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 */
};
@ -138,9 +138,9 @@ struct macnet_driver_s
/* 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 */
@ -223,7 +223,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 =
@ -250,11 +250,17 @@ static void macnet_notify(FAR const struct mac802154_maccb_s *maccb,
* 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 +270,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 +306,7 @@ static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb,
*/
ieee802154_ind_free(ind);
return OK;
}
/****************************************************************************
@ -993,7 +1021,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.
@ -1072,6 +1100,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;