diff --git a/.gitignore b/.gitignore
index 4095c1a294f8af9f183c495a957119b83afb0d9b..8052befe0fdc09e7caeadf9abb1e3784c2a8bb96 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ core
 /.config
 /.config.old
 /.version
+/defconfig
 /Make.defs
 /nuttx
 /nuttx.*
diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h
index 7c34217ae9b0dc9494245fff48ab334af84478c1..cc6034c472668a928d0b0c4f829694234ea8d657 100644
--- a/include/nuttx/net/netdev.h
+++ b/include/nuttx/net/netdev.h
@@ -318,12 +318,13 @@ struct net_driver_s
    *
    * There are two lists associated with each device:
    *
-   *   1) d_pktcb - For connection/port oriented events for certain
+   *   1) d_conncb - For connection/port oriented events for certain
    *      socket-less packet transfers.  There events include:
    *
-   *        ICMP data receipt: ICMP_NEWDATA, ICMPv6_NEWDATA
-   *        ICMP ECHO replies: ICMP_ECHOREPLY, ICMPv6_ECHOREPLY
+   *        ICMP data receipt:     ICMP_NEWDATA, ICMPv6_NEWDATA
+   *        ICMP ECHO replies:     ICMP_ECHOREPLY, ICMPv6_ECHOREPLY
    *        Driver Tx poll events: ARP_POLL, ICMP_POLL. ICMPv6_POLL
+   *        IP Forwarding:         IPFWD_POLL
    *
    *   2) d_devcb - For non-data, device related events that apply to all
    *      transfers or connections involving this device:
diff --git a/net/devif/devif.h b/net/devif/devif.h
index 99b389c9b1d36c96e7e9fb3b48f2ba685e34a0d4..3a2215bf940d13b70386da315b5e9f7953d1b8d9 100644
--- a/net/devif/devif.h
+++ b/net/devif/devif.h
@@ -148,6 +148,14 @@
  *                        is set differently
  *                   OUT: Not used
  *
+ *   IPFWD_POLL       IN: Used for polling for forwarded packets layer.  This
+ *                        is provided periodically from the drivers to support
+ *                        to check if there is a packet waiting to be forward
+ *                        on the device.  This is a device oriented event,
+ *                        not associated with a socket.  The appdata pointer
+ *                        The appdata pointer is not used in this case.
+ *                   OUT: Not used
+ *
  *   ICMP_ECHOREPLY   IN: An ICMP Echo Reply has been received.  Used to support
  *                        ICMP ping from the socket layer. (ICMPv4 only)
  *                   OUT: Cleared (only) by the socket layer logic to indicate
@@ -164,7 +172,7 @@
  *                   OUT: Not used
  */
 
-/* Connection specific events */
+/* Bits 0-9: Connection specific event bits */
 
 #define TCP_ACKDATA      (1 << 0)
 #define TCP_NEWDATA      (1 << 1)
@@ -178,23 +186,33 @@
 #define UDP_POLL         TCP_POLL
 #define PKT_POLL         TCP_POLL
 #define WPAN_POLL        TCP_POLL
-#define IPFWD_POLL       TCP_POLL
 #define TCP_BACKLOG      (1 << 5)
 #define TCP_CLOSE        (1 << 6)
 #define TCP_ABORT        (1 << 7)
 #define TCP_CONNECTED    (1 << 8)
 #define TCP_TIMEDOUT     (1 << 9)
 
-/* Device specific events */
+/* Bits 10-12: Device specific event bits */
 
 #define ICMP_NEWDATA     TCP_NEWDATA
 #define ICMPv6_NEWDATA   TCP_NEWDATA
-#define ARP_POLL         (1 << 10)
-#define ICMP_POLL        (1 << 11)
-#define ICMPv6_POLL      (1 << 12)
-#define ICMP_ECHOREPLY   (1 << 13)
-#define ICMPv6_ECHOREPLY (1 << 14)
-#define NETDEV_DOWN      (1 << 15)
+#define ICMP_ECHOREPLY   (1 << 10)
+#define ICMPv6_ECHOREPLY (1 << 11)
+#define NETDEV_DOWN      (1 << 12)
+
+/* Bits 13-15: Encoded device specific poll events.  Unlike connection
+ * oriented poll events, device related poll events must distinguish
+ * between what is being polled for since the callbacks all reside in
+ * the same list in the network device structure.
+ */
+
+#define DEVPOLL_SHIFT    (13)
+#define DEVPOLL_MASK     (7 << DEVPOLL_SHIFT)
+#  define DEVPOLL_NONE   (0 << DEVPOLL_SHIFT)
+#  define ARP_POLL       (1 << DEVPOLL_SHIFT)
+#  define ICMP_POLL      (2 << DEVPOLL_SHIFT)
+#  define ICMPv6_POLL    (3 << DEVPOLL_SHIFT)
+#  define IPFWD_POLL     (4 << DEVPOLL_SHIFT)
 
 /* The set of events that and implications to the TCP connection state */
 
diff --git a/net/devif/devif_callback.c b/net/devif/devif_callback.c
index bb8867b73ffdfbdee563c5dbe6a6589451c7c6cc..c88dda744c36441f02925128eac2b22a28f3d2ba 100644
--- a/net/devif/devif_callback.c
+++ b/net/devif/devif_callback.c
@@ -41,6 +41,7 @@
 #if defined(CONFIG_NET)
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <string.h>
 #include <debug.h>
 #include <assert.h>
@@ -162,6 +163,45 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
     }
 }
 
+/****************************************************************************
+ * Name: devif_event_trigger
+ *
+ * Description:
+ *   Return true if the current set of events should trigger a callback to
+ *   occur.
+ *
+ * Input paramters:
+ *   events   - The set of events that has occurred.
+ *   triggers - The set of events that will trigger a callback.
+ *
+ ****************************************************************************/
+
+static bool devif_event_trigger(uint16_t events, uint16_t triggers)
+{
+  /* The events are divided into a set of individual bits that may be ORed
+   * together PLUS a field that encodes a single poll event.
+   *
+   * First check if any of the individual event bits will trigger the
+   * callback.
+   */
+
+  if ((events & triggers & ~DEVPOLL_MASK) != 0)
+    {
+      return true;
+    }
+
+  /* No... check the encoded device event. */
+
+  if ((events & DEVPOLL_MASK) == (triggers & DEVPOLL_MASK))
+    {
+      return true;
+    }
+
+  /* No.. this event set will not generate the callback */
+
+  return false;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -335,7 +375,7 @@ void devif_dev_callback_free(FAR struct net_driver_s *dev,
    * was allocated and the time when the callback was freed.
    */
 
-  if (dev && netdev_verify(dev))
+  if (dev != NULL && netdev_verify(dev))
     {
       /* The device reference is valid.. the use the list pointer in the
        * device structure as well.
@@ -400,7 +440,7 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, void *pvconn,
 
       /* Check if this callback handles any of the events in the flag set */
 
-      if (list->event && (flags & list->flags) != 0)
+      if (list->event != NULL && devif_event_trigger(flags, list->flags))
         {
           /* Yes.. perform the callback.  Actions perform by the callback
            * may delete the current list entry or add a new list entry to
@@ -464,7 +504,7 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, void *pvconn,
 
       /* Check if this callback handles any of the events in the flag set */
 
-      if (cb->event && (flags & cb->flags) != 0)
+      if (cb->event != NULL && devif_event_trigger(flags, cb->flags))
         {
           /* Yes.. perform the callback.  Actions perform by the callback
            * may delete the current list entry or add a new list entry to
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 73c5050f588e6de3b850e656a427e6ebfe81d9b0..6f37768d6b68129b047c084dcd8c84567bec91d2 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -56,6 +56,7 @@
 #include "icmp/icmp.h"
 #include "icmpv6/icmpv6.h"
 #include "igmp/igmp.h"
+#include "ipforward/ipforward.h"
 #include "sixlowpan/sixlowpan.h"
 
 /****************************************************************************
@@ -166,8 +167,8 @@ static void devif_packet_conversion(FAR struct net_driver_s *dev,
  *   Poll all packet connections for available packets to send.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called
- *   from the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
@@ -259,13 +260,18 @@ static inline int devif_poll_icmpv6(FAR struct net_driver_s *dev,
  *
  ****************************************************************************/
 
-#if defined(CONFIG_NET_IPFORWARD) || defined(CONFIG_NETDEV_MULTINIC)
+#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
 static inline int devif_poll_forward(FAR struct net_driver_s *dev,
                                      devif_poll_callback_t callback)
 {
-  /* Perform the ICMPv6 poll */
+  /* Perform the forwarding poll */
+
+  ipfwd_poll(dev);
 
-  devif_dev_event(dev, NULL, IPFWD_POLL);
+  /* NOTE: that 6LoWPAN packet conversions are handled differently for
+   * forwarded packets.  That is because we don't know what the packet
+   * type is at this point; not within peeking into the device's d_buf.
+   */
 
   /* Call back into the driver */
 
@@ -280,8 +286,8 @@ static inline int devif_poll_forward(FAR struct net_driver_s *dev,
  *   Poll all IGMP connections for available packets to send.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called
- *   from the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
@@ -310,8 +316,8 @@ static inline int devif_poll_igmp(FAR struct net_driver_s *dev,
  *   Poll all UDP connections for available packets to send.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called
- *   from the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
@@ -350,8 +356,8 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
  *   Poll all UDP connections for available packets to send.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called
- *   from the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
@@ -393,8 +399,8 @@ static inline int devif_poll_tcp_connections(FAR struct net_driver_s *dev,
  *   TCP connection.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called
- *   from the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
@@ -453,8 +459,8 @@ static inline int devif_poll_tcp_timer(FAR struct net_driver_s *dev,
  *   out the packet.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called
- *   from the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
@@ -530,7 +536,7 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
 
   if (!bstop)
 #endif
-#if defined(CONFIG_NET_IPFORWARD) || defined(CONFIG_NETDEV_MULTINIC)
+#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
     {
       /* Traverse all of the tasks waiting to forward a packet to this device. */
 
@@ -565,8 +571,8 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
  *   out the packet.
  *
  * Assumptions:
- *   This function is called from the MAC device driver and may be called from
- *   the timer interrupt/watchdog handle level.
+ *   This function is called from the MAC device driver with the network
+ *   locked.
  *
  ****************************************************************************/
 
diff --git a/net/ipforward/Make.defs b/net/ipforward/Make.defs
index cc46826da53f56072fa0bc473e5f97159d7ee58b..c8ad408c564595b7a2e4556705520dcf21909655 100644
--- a/net/ipforward/Make.defs
+++ b/net/ipforward/Make.defs
@@ -37,8 +37,6 @@
 
 ifeq ($(CONFIG_NET_IPFORWARD),y)
 
-NET_CSRCS += ipfwd_forward.c
-
 ifeq ($(CONFIG_NET_IPv4),y)
 NET_CSRCS += ipv4_forward.c
 endif
@@ -48,7 +46,7 @@ NET_CSRCS += ipv6_forward.c
 endif
 
 ifeq ($(CONFIG_NETDEV_MULTINIC),y)
-NET_CSRCS += ipfwd_alloc.c
+NET_CSRCS += ipfwd_alloc.c ipfwd_forward.c ipfwd_poll.c
 endif
 
 ifeq ($(CONFIG_NET_STATISTICS),y)
diff --git a/net/ipforward/ipforward.h b/net/ipforward/ipforward.h
index a267c1f901634d8364d18b58b99b351e2fc8829b..e88c23a6598dce0165bb8eeb903ce1f35f314081 100644
--- a/net/ipforward/ipforward.h
+++ b/net/ipforward/ipforward.h
@@ -63,6 +63,11 @@
 #  define CONFIG_NET_IPFORWARD_NSTRUCT 4
 #endif
 
+/* Allocate a new IP forwarding data callback */
+
+#define ipfwd_callback_alloc(dev)   devif_callback_alloc(dev, &(dev)->d_conncb)
+#define ipfwd_callback_free(dev,cb) devif_dev_callback_free(dev, cb)
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -240,6 +245,20 @@ void devif_forward(FAR struct forward_s *fwd);
 
 int ipfwd_forward(FAR struct forward_s *fwd);
 
+/****************************************************************************
+ * Name: ipfwd_poll
+ *
+ * Description:
+ *   Poll all pending transfer for ARP requests to send.
+ *
+ * Assumptions:
+ *   This function is called from the MAC device driver indirectly through
+ *   devif_poll() and devif_timer().
+ *
+ ****************************************************************************/
+
+void ipfwd_poll(FAR struct net_driver_s *dev);
+
 #endif /* CONFIG_NETDEV_MULTINIC */
 
 /****************************************************************************
diff --git a/net/ipforward/ipfwd_forward.c b/net/ipforward/ipfwd_forward.c
index 962713425e4bd6b7878ca0fc51c115208ce271c3..9899fadcc739676ad9642b696984575db752ca69 100644
--- a/net/ipforward/ipfwd_forward.c
+++ b/net/ipforward/ipfwd_forward.c
@@ -264,6 +264,7 @@ static uint16_t ipfwd_interrupt(FAR struct net_driver_s *dev, FAR void *conn,
           /* Copy the user data into d_appdata and send it. */
 
           devif_forward(fwd);
+          flags &= ~DEVPOLL_MASK;
 
           /* Check if the destination IP address is in the ARP or Neighbor
            * table.  If not, then the send won't actually make it out... it
@@ -282,7 +283,7 @@ static uint16_t ipfwd_interrupt(FAR struct net_driver_s *dev, FAR void *conn,
       fwd->f_cb->priv  = NULL;
       fwd->f_cb->event = NULL;
 
-      devif_conn_callback_free(dev, fwd->f_cb, NULL);
+      ipfwd_callback_free(dev, fwd->f_cb);
 
       /* Free any IOBs */
 
@@ -332,7 +333,7 @@ int ipfwd_forward(FAR struct forward_s *fwd)
 
   /* Set up the callback in the connection */
 
-  fwd->f_cb = devif_callback_alloc(fwd->f_dev, NULL);
+  fwd->f_cb = ipfwd_callback_alloc(fwd->f_dev);
   if (fwd->f_cb != NULL)
     {
       fwd->f_cb->flags   = (IPFWD_POLL | NETDEV_DOWN);
diff --git a/net/ipforward/ipfwd_poll.c b/net/ipforward/ipfwd_poll.c
new file mode 100644
index 0000000000000000000000000000000000000000..e9ba676c21a0bb5e4259fb28dd26c215c4c758a1
--- /dev/null
+++ b/net/ipforward/ipfwd_poll.c
@@ -0,0 +1,206 @@
+/****************************************************************************
+ * net/ipforward/ipfwd_poll.c
+ *
+ *   Copyright (C) 2017 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include <nuttx/net/netdev.h>
+
+#include "devif/devif.h"
+#include "ipforward/ipforward.h"
+
+#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipfwd_packet_proto
+ *
+ * Description:
+ *   Generic output conversion hook.  Only needed for IEEE802.15.4 for now
+ *   but this is a point where support for other conversions may be
+ *   provided.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_6LOWPAN
+static int ipfwd_packet_proto(FAR struct net_driver_s *dev)
+{
+  FAR struct ipv6_hdr_s *ipv6;
+  int llhdrlen = NET_LL_HDRLEN(dev);
+
+  /* Make sure the there is something in buffer that is at least as large as
+   * the IPv6_HDR.
+   */
+
+  if (dev->d_len > (IPv6_HDRLEN + llhdrlen))
+    {
+#ifdef CONFIG_NET_MULTILINK
+      /* Handle the case where multiple link layer protocols are supported */
+
+      if (dev->d_lltype == NET_LL_IEEE802154)
+#endif
+        {
+          /* There should be an IPv6 packet in the at the beginning of the debugger */
+
+          ipv6 = (FAR struct ipv6_hdr_s *)&dev->d_buf[llhdrlen];
+          if ((ipv6->vtc & IP_VERSION_MASK) == IPv6_VERSION)
+            {
+              /* Yes.. return the L2 protocol of the packet */
+
+              return ipv6->proto;
+            }
+        }
+    }
+
+  return -EPROTO;
+}
+#endif /* CONFIG_NET_6LOWPAN */
+
+/****************************************************************************
+ * Name: ipfwd_packet_conversion
+ *
+ * Description:
+ *   Generic output conversion hook.  Only needed for IEEE802.15.4 for now
+ *   but this is a point where support for other conversions may be
+ *   provided.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_6LOWPAN
+static void ipfwd_packet_conversion(FAR struct net_driver_s *dev, int proto)
+{
+#ifdef CONFIG_NET_MULTILINK
+  /* Handle the case where multiple link layer protocols are supported */
+
+  if (dev->d_len > 0 && dev->d_lltype == NET_LL_IEEE802154)
+#else
+  if (dev->d_len > 0)
+#endif
+    {
+#ifdef CONFIG_NET_TCP
+      if (proto == IP_PROTO_TCP)
+        {
+          /* Let 6LoWPAN convert IPv6 TCP output into IEEE802.15.4 frames. */
+
+          sixlowpan_tcp_send(dev, dev, ipv6);
+        }
+      else
+#endif
+#ifdef CONFIG_NET_UDP
+      if (proto == IP_PROTO_UDP)
+        {
+          /* Let 6LoWPAN convert IPv6 UDP output into IEEE802.15.4 frames. */
+
+          sixlowpan_udp_send(dev, dev, ipv6);
+        }
+      else
+#endif
+#ifdef CONFIG_NET_ICMPv6
+      if (proto == IP_PROTO_ICMP6)
+        {
+          /* Let 6LoWPAN convert IPv6 UDP output into IEEE802.15.4 frames. */
+
+          nwerr("ERROR:  Missing support for ICMPv6 packet forwarding\n");
+        }
+      else
+#endif
+        {
+          nwarn("WARNING: Non-TCP packet dropped.  Packet type: %u\n", proto);
+        }
+
+      dev->d_len = 0;
+    }
+}
+#endif /* CONFIG_NET_6LOWPAN */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ipfwd_poll
+ *
+ * Description:
+ *   Poll all pending transfer for ARP requests to send.
+ *
+ * Assumptions:
+ *   This function is called from the MAC device driver indirectly through
+ *   devif_poll() and devif_timer().
+ *
+ ****************************************************************************/
+
+void ipfwd_poll(FAR struct net_driver_s *dev)
+{
+  uint16_t flags;
+
+  /* Setup for the callback (most of these do not apply) */
+
+  dev->d_appdata = NULL;
+  dev->d_len     = 0;
+  dev->d_sndlen  = 0;
+
+  /* Perform the forwarding callbacks.  Returns the new set of flags.  If
+   * the packet was fowarded, then the new set will be zero.
+   */
+
+  flags = devif_conn_event(dev, NULL, IPFWD_POLL, dev->d_conncb);
+
+#ifdef CONFIG_NET_6LOWPAN
+  if ((flags & DEVPOLL_MASK) == 0)
+    {
+      /* Get the L2 protocol of packet in the device's d_buf */
+
+      int proto = ipfwd_packet_proto(dev);
+      if (proto >= 0)
+        {
+          /* Perform any necessary conversions on the forwarded packet */
+
+          ipfwd_packet_conversion(dev, proto);
+        }
+    }
+#else
+  UNUSED(flags);
+#endif
+}
+
+#endif /* CONFIG_NET_ARP_SEND && CONFIG_NETDEV_MULTINIC */