From 83d8a7ed8ba317462943fa1b953d88c6fc33c786 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Sun, 18 Jun 2017 10:53:31 -0400 Subject: [PATCH 1/6] wireless/ieee802154: Renames Kconfig option, adds option for unimplemented receiver priority. --- wireless/ieee802154/Kconfig | 38 ++++++++++++++++++++++++++++------- wireless/ieee802154/Make.defs | 2 +- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index 7ffe2654f4..107063a43e 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -21,13 +21,7 @@ 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" @@ -83,6 +77,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_RECEIVERPRIORITY + 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" diff --git a/wireless/ieee802154/Make.defs b/wireless/ieee802154/Make.defs index da1b1bc05e..26705a51a7 100644 --- a/wireless/ieee802154/Make.defs +++ b/wireless/ieee802154/Make.defs @@ -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 From 2ef49eb3bd8e3fa4c345a67585606135f964d53b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 18 Jun 2017 09:01:18 -0600 Subject: [PATCH 2/6] Update TODO and README --- TODO | 21 ++++++++++++--------- net/sixlowpan/README.txt | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/TODO b/TODO index 1cac77e862..f5975ae90b 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/net/sixlowpan/README.txt b/net/sixlowpan/README.txt index 9eb848144e..4031af925d 100644 --- a/net/sixlowpan/README.txt +++ b/net/sixlowpan/README.txt @@ -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: From 2d4ba3ee3f0d7311cb3325f9ad6719617f7830fc Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 18 Jun 2017 11:00:47 -0600 Subject: [PATCH 3/6] IEEE 802.15.4 MAC: Add list management and prioritization logic that will permit the MAC layer to support bound multiple clients. --- .../clicker2-stm32/mrf24j40-6lowpan/defconfig | 4 +- configs/clicker2-stm32/mrf24j40-mac/defconfig | 8 +- configs/sim/sixlowpan/defconfig | 2 +- sched/sched/sched_addprioritized.c | 4 +- wireless/ieee802154/Kconfig | 26 ++++-- wireless/ieee802154/mac802154.c | 79 ++++++++++++++++--- wireless/ieee802154/mac802154.h | 20 +++-- wireless/ieee802154/mac802154_bind.c | 35 +++++++- wireless/ieee802154/mac802154_device.c | 26 ++++-- wireless/ieee802154/mac802154_internal.h | 2 +- wireless/ieee802154/mac802154_netdev.c | 48 ++++++++--- 11 files changed, 204 insertions(+), 50 deletions(-) diff --git a/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig b/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig index b202b30aa8..df21e0d03e 100644 --- a/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig +++ b/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig @@ -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 diff --git a/configs/clicker2-stm32/mrf24j40-mac/defconfig b/configs/clicker2-stm32/mrf24j40-mac/defconfig index 8ecd37bd89..d6ba224b4e 100644 --- a/configs/clicker2-stm32/mrf24j40-mac/defconfig +++ b/configs/clicker2-stm32/mrf24j40-mac/defconfig @@ -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 diff --git a/configs/sim/sixlowpan/defconfig b/configs/sim/sixlowpan/defconfig index 5613379e8e..3c2ac60369 100644 --- a/configs/sim/sixlowpan/defconfig +++ b/configs/sim/sixlowpan/defconfig @@ -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 diff --git a/sched/sched/sched_addprioritized.c b/sched/sched/sched_addprioritized.c index 349889f488..1a990bd04d 100644 --- a/sched/sched/sched_addprioritized.c +++ b/sched/sched/sched_addprioritized.c @@ -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 diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index 107063a43e..a471e4804e 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -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 diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index f9322c36df..fa51213218 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -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); } } diff --git a/wireless/ieee802154/mac802154.h b/wireless/ieee802154/mac802154.h index 40d00c9d69..90ff021952 100644 --- a/wireless/ieee802154/mac802154.h +++ b/wireless/ieee802154/mac802154.h @@ -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 diff --git a/wireless/ieee802154/mac802154_bind.c b/wireless/ieee802154/mac802154_bind.c index c173aef477..9b6bacea39 100644 --- a/wireless/ieee802154/mac802154_bind.c +++ b/wireless/ieee802154/mac802154_bind.c @@ -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; } - diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index b03ce94ba8..1d634f9018 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -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; diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index 51c4a1c706..adfc176c03 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -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 */ diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index 7fcd25e3af..41946846b9 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -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; From 50df37931d848852af6ba7a959bc5a3728649c50 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 18 Jun 2017 11:29:09 -0600 Subject: [PATCH 4/6] ieee802.15.4: Missing one name change --- configs/clicker2-stm32/src/stm32_mrf24j40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/clicker2-stm32/src/stm32_mrf24j40.c b/configs/clicker2-stm32/src/stm32_mrf24j40.c index 1d5733edde..6ff5ad7bae 100644 --- a/configs/clicker2-stm32/src/stm32_mrf24j40.c +++ b/configs/clicker2-stm32/src/stm32_mrf24j40.c @@ -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(). */ From 6162a84f807136cf1f5cc8d139cf66da099ee40f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 18 Jun 2017 13:33:07 -0600 Subject: [PATCH 5/6] ieee 802.15.4: Need counting protection on the logic that releases the notification resources. Otherwise, notification handlers may be operating with a stale pointer. --- wireless/ieee802154/mac802154.c | 55 ++++++++----------- wireless/ieee802154/mac802154_assoc.c | 11 ++-- wireless/ieee802154/mac802154_bind.c | 7 +++ wireless/ieee802154/mac802154_internal.h | 4 +- wireless/ieee802154/mac802154_netdev.c | 4 ++ wireless/ieee802154/mac802154_notif.c | 69 +++++++++++++++++++++--- wireless/ieee802154/mac802154_notif.h | 7 ++- wireless/ieee802154/mac802154_poll.c | 9 ++-- 8 files changed, 112 insertions(+), 54 deletions(-) diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index fa51213218..2c60866e71 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -73,11 +73,6 @@ 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, @@ -496,34 +491,6 @@ 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 * @@ -667,6 +634,7 @@ static void mac802154_txdone_worker(FAR void *arg) mac802154_takesem(&priv->exclsem, false); } break; + case IEEE802154_FRAME_COMMAND: { switch (priv->curr_cmd) @@ -674,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. * @@ -697,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 @@ -722,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 @@ -941,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; } diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index d9ab6cb19d..c5ef212da0 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -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); } diff --git a/wireless/ieee802154/mac802154_bind.c b/wireless/ieee802154/mac802154_bind.c index 9b6bacea39..091d83814a 100644 --- a/wireless/ieee802154/mac802154_bind.c +++ b/wireless/ieee802154/mac802154_bind.c @@ -105,5 +105,12 @@ int mac802154_bind(MACHANDLE mac, FAR struct mac802154_maccb_s *cb) prev->flink = cb; } + /* Keep track of the number of clients requesting notification */ + + if (cb->notify != NULL) + { + priv->nclients++; + } + return OK; } diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index adfc176c03..798f48a927 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -150,7 +150,9 @@ struct ieee802154_privmac_s 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 diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index 41946846b9..be9c3fc678 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -244,6 +244,10 @@ static void macnet_notify(FAR struct mac802154_maccb_s *maccb, default: break; } + + /* Free the event notification */ + + mac802154_notif_free(priv->md_mac, notif); } /**************************************************************************** diff --git a/wireless/ieee802154/mac802154_notif.c b/wireless/ieee802154/mac802154_notif.c index 15368a5483..bce299c139 100644 --- a/wireless/ieee802154/mac802154_notif.c +++ b/wireless/ieee802154/mac802154_notif.c @@ -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; -} \ No newline at end of file +} + +/**************************************************************************** + * 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); + } + } +} diff --git a/wireless/ieee802154/mac802154_notif.h b/wireless/ieee802154/mac802154_notif.h index 3cf088163d..3c6bdd3523 100644 --- a/wireless/ieee802154/mac802154_notif.h +++ b/wireless/ieee802154/mac802154_notif.h @@ -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 */ \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_poll.c b/wireless/ieee802154/mac802154_poll.c index 3f74b55224..57c3154991 100644 --- a/wireless/ieee802154/mac802154_poll.c +++ b/wireless/ieee802154/mac802154_poll.c @@ -50,8 +50,6 @@ #include #include -#include - #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); } \ No newline at end of file From 84a75996fb97c2f6143585e3bfa8d29d66bc29d2 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 18 Jun 2017 15:26:56 -0600 Subject: [PATCH 6/6] IEEE 802.15.4 Network Driver: Add logic to setup the network mask, update the MAC-based IPv6 addressing when the network is brought up. The idea is that addressing changes are supposed to occur only while the network is down but won't take effect until the network is up again. --- configs/clicker2-stm32/README.txt | 4 +- .../clicker2-stm32/mrf24j40-6lowpan/defconfig | 2 +- wireless/ieee802154/mac802154_loopback.c | 51 ++++- wireless/ieee802154/mac802154_netdev.c | 189 ++++++++++++++++-- 4 files changed, 213 insertions(+), 33 deletions(-) diff --git a/configs/clicker2-stm32/README.txt b/configs/clicker2-stm32/README.txt index 274b9a2b0c..a2287418b3 100644 --- a/configs/clicker2-stm32/README.txt +++ b/configs/clicker2-stm32/README.txt @@ -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 diff --git a/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig b/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig index df21e0d03e..a8ba381b69 100644 --- a/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig +++ b/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig @@ -1450,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 diff --git a/wireless/ieee802154/mac802154_loopback.c b/wireless/ieee802154/mac802154_loopback.c index 33bbb3f614..e4e54c9b60 100644 --- a/wireless/ieee802154/mac802154_loopback.c +++ b/wireless/ieee802154/mac802154_loopback.c @@ -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 */ diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index be9c3fc678..71914e3ead 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -136,6 +136,11 @@ 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 struct mac802154_maccb_s *maccb, @@ -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 * @@ -656,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; } /**************************************************************************** @@ -1094,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 */