diff --git a/drivers/xbee/gnrc_xbee.c b/drivers/xbee/gnrc_xbee.c
index 8d66233c64d6551f45d648eb70a0e6f730cececa..9f52974b4028591aa45941f4087b9b48d5f54419 100644
--- a/drivers/xbee/gnrc_xbee.c
+++ b/drivers/xbee/gnrc_xbee.c
@@ -153,10 +153,10 @@ static int xbee_adpt_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
 
 #ifdef MODULE_NETSTATS_L2
     if (hdr->flags & BCAST) {
-        netif->dev->stats.tx_mcast_count++;
+        netif->stats.tx_mcast_count++;
     }
     else {
-        netif->dev->stats.tx_unicast_count++;
+        netif->stats.tx_unicast_count++;
     }
 #endif
     DEBUG("[xbee-gnrc] send: triggering the drivers send function\n");
diff --git a/sys/include/net/gnrc/netif.h b/sys/include/net/gnrc/netif.h
index 37eb8413e63bda44f06930c356b608b6b16797a1..a69948d68388bcc63afd3be7d763f9b4784ba7f2 100644
--- a/sys/include/net/gnrc/netif.h
+++ b/sys/include/net/gnrc/netif.h
@@ -47,6 +47,9 @@
 #include "net/ndp.h"
 #include "net/netdev.h"
 #include "net/netopt.h"
+#ifdef MODULE_NETSTATS_L2
+#include "net/netstats.h"
+#endif
 #include "rmutex.h"
 
 #ifdef __cplusplus
@@ -65,6 +68,9 @@ typedef struct {
     const gnrc_netif_ops_t *ops;            /**< Operations of the network interface */
     netdev_t *dev;                          /**< Network device of the network interface */
     rmutex_t mutex;                         /**< Mutex of the interface */
+#ifdef MODULE_NETSTATS_L2
+    netstats_t stats;                       /**< transceiver's statistics */
+#endif
 #if defined(MODULE_GNRC_IPV6) || DOXYGEN
     gnrc_netif_ipv6_t ipv6;                 /**< IPv6 component */
 #endif
diff --git a/sys/net/gnrc/link_layer/gomach/gomach_internal.c b/sys/net/gnrc/link_layer/gomach/gomach_internal.c
index 3b6618324509a85ea2f1338a81a8744494fce8bb..5db84252456925b45676d4a6f178ec03c325936b 100644
--- a/sys/net/gnrc/link_layer/gomach/gomach_internal.c
+++ b/sys/net/gnrc/link_layer/gomach/gomach_internal.c
@@ -103,10 +103,10 @@ int _gnrc_gomach_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
 #ifdef MODULE_NETSTATS_L2
     if (netif_hdr->flags &
             (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
-        netif->dev->stats.tx_mcast_count++;
+        netif->stats.tx_mcast_count++;
     }
     else {
-        netif->dev->stats.tx_unicast_count++;
+        netif->stats.tx_unicast_count++;
     }
 #endif
 #ifdef MODULE_GNRC_MAC
diff --git a/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c b/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c
index f28ec6468997ed70081f23061c683977bc377287..371c9430ada792771d041ea6ca975e248d8cd9d4 100644
--- a/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c
+++ b/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c
@@ -90,10 +90,10 @@ int _gnrc_lwmac_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
 #ifdef MODULE_NETSTATS_L2
     if (netif_hdr->flags &
             (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
-        netif->dev->stats.tx_mcast_count++;
+        netif->stats.tx_mcast_count++;
     }
     else {
-        netif->dev->stats.tx_unicast_count++;
+        netif->stats.tx_unicast_count++;
     }
 #endif
 #ifdef MODULE_GNRC_MAC
diff --git a/sys/net/gnrc/netif/ethernet/gnrc_netif_ethernet.c b/sys/net/gnrc/netif/ethernet/gnrc_netif_ethernet.c
index 703550a2d59204ca5b06ffbbaa88c957f868e8a6..a12c6f9fbb7e2928e4395d2fe7d9aef31e59f1f5 100644
--- a/sys/net/gnrc/netif/ethernet/gnrc_netif_ethernet.c
+++ b/sys/net/gnrc/netif/ethernet/gnrc_netif_ethernet.c
@@ -145,10 +145,10 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
 #ifdef MODULE_NETSTATS_L2
     if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) ||
         (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
-        dev->stats.tx_mcast_count++;
+        netif->stats.tx_mcast_count++;
     }
     else {
-        dev->stats.tx_unicast_count++;
+        netif->stats.tx_unicast_count++;
     }
 #endif
     res = dev->driver->send(dev, &iolist);
@@ -183,6 +183,10 @@ static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif)
             DEBUG("gnrc_netif_ethernet: read error.\n");
             goto safe_out;
         }
+#ifdef MODULE_NETSTATS_L2
+        netif->stats.rx_count++;
+        netif->stats.rx_bytes += nread;
+#endif
 
         if (nread < bytes_expected) {
             /* we've got less than the expected packet size,
diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c
index df0085d371ddc7abaae2ca9a14abdf8b39049096..09da4038cd243c9363624f7bee72d35d75dd67f0 100644
--- a/sys/net/gnrc/netif/gnrc_netif.c
+++ b/sys/net/gnrc/netif/gnrc_netif.c
@@ -25,7 +25,7 @@
 #include "net/gnrc/ipv6/nib.h"
 #include "net/gnrc/ipv6.h"
 #endif /* MODULE_GNRC_IPV6_NIB */
-#ifdef MODULE_NETSTATS_IPV6
+#ifdef MODULE_NETSTATS
 #include "net/netstats.h"
 #endif
 #include "fmt.h"
@@ -126,6 +126,13 @@ int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt)
                     *((netstats_t **)opt->data) = &netif->ipv6.stats;
                     res = sizeof(&netif->ipv6.stats);
                     break;
+#endif
+#ifdef MODULE_NETSTATS_L2
+                case NETSTATS_LAYER2:
+                    assert(opt->data_len == sizeof(netstats_t *));
+                    *((netstats_t **)opt->data) = &netif->stats;
+                    res = sizeof(&netif->stats);
+                    break;
 #endif
                 default:
                     /* take from device */
@@ -1196,6 +1203,9 @@ static void *_gnrc_netif_thread(void *args)
     if (netif->ops->init) {
         netif->ops->init(netif);
     }
+#ifdef MODULE_NETSTATS_L2
+    memset(&netif->stats, 0, sizeof(netstats_t));
+#endif
     /* now let rest of GNRC use the interface */
     gnrc_netif_release(netif);
 
@@ -1215,6 +1225,11 @@ static void *_gnrc_netif_thread(void *args)
                     DEBUG("gnrc_netif: error sending packet %p (code: %u)\n",
                           msg.content.ptr, res);
                 }
+#ifdef MODULE_NETSTATS_L2
+                else {
+                    netif->stats.tx_bytes += res;
+                }
+#endif
                 break;
             case GNRC_NETAPI_MSG_TYPE_SET:
                 opt = msg.content.ptr;
@@ -1287,25 +1302,24 @@ static void _event_cb(netdev_t *dev, netdev_event_t event)
     }
     else {
         DEBUG("gnrc_netif: event triggered -> %i\n", event);
+        gnrc_pktsnip_t *pkt = NULL;
         switch (event) {
-            case NETDEV_EVENT_RX_COMPLETE: {
-                    gnrc_pktsnip_t *pkt = netif->ops->recv(netif);
-
-                    if (pkt) {
-                        _pass_on_packet(pkt);
-                    }
+            case NETDEV_EVENT_RX_COMPLETE:
+                pkt = netif->ops->recv(netif);
+                if (pkt) {
+                    _pass_on_packet(pkt);
                 }
                 break;
 #ifdef MODULE_NETSTATS_L2
             case NETDEV_EVENT_TX_MEDIUM_BUSY:
                 /* we are the only ones supposed to touch this variable,
                  * so no acquire necessary */
-                dev->stats.tx_failed++;
+                netif->stats.tx_failed++;
                 break;
             case NETDEV_EVENT_TX_COMPLETE:
                 /* we are the only ones supposed to touch this variable,
                  * so no acquire necessary */
-                dev->stats.tx_success++;
+                netif->stats.tx_success++;
                 break;
 #endif
             default:
diff --git a/sys/net/gnrc/netif/gnrc_netif_raw.c b/sys/net/gnrc/netif/gnrc_netif_raw.c
index cc8760b4ce7cef2c5cdb23af59b03526c0f3ac30..886c00731e2bc25c939251a97fc26f0b7dccf2a4 100644
--- a/sys/net/gnrc/netif/gnrc_netif_raw.c
+++ b/sys/net/gnrc/netif/gnrc_netif_raw.c
@@ -70,6 +70,11 @@ static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif)
             gnrc_pktbuf_release(pkt);
             return NULL;
         }
+#ifdef MODULE_NETSTATS_L2
+        netif->stats.rx_count++;
+        netif->stats.rx_bytes += nread;
+#endif
+
         if (nread < bytes_expected) {
             /* we've got less then the expected packet size,
              * so free the unused space.*/
@@ -102,7 +107,7 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
     netdev_t *dev = netif->dev;
 
 #ifdef MODULE_NETSTATS_L2
-    dev->stats.tx_unicast_count++;
+    netif->stats.tx_unicast_count++;
 #endif
 
     res = dev->driver->send(dev, (iolist_t *)pkt);
diff --git a/sys/net/gnrc/netif/ieee802154/gnrc_netif_ieee802154.c b/sys/net/gnrc/netif/ieee802154/gnrc_netif_ieee802154.c
index d99653a8bf0af36a35fdece687b14845dd65a760..fc2bbddeb5b8f6d2497f6ec3ac6dc0d7b73a04de 100644
--- a/sys/net/gnrc/netif/ieee802154/gnrc_netif_ieee802154.c
+++ b/sys/net/gnrc/netif/ieee802154/gnrc_netif_ieee802154.c
@@ -95,6 +95,11 @@ static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif)
             gnrc_pktbuf_release(pkt);
             return NULL;
         }
+#ifdef MODULE_NETSTATS_L2
+        netif->stats.rx_count++;
+        netif->stats.rx_bytes += nread;
+#endif
+
         if (netif->flags & GNRC_NETIF_FLAGS_RAWMODE) {
             /* Raw mode, skip packet processing, but provide rx_info via
              * GNRC_NETTYPE_NETIF */
@@ -241,10 +246,10 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
 #ifdef MODULE_NETSTATS_L2
     if (netif_hdr->flags &
             (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
-        netif->dev->stats.tx_mcast_count++;
+        netif->stats.tx_mcast_count++;
     }
     else {
-        netif->dev->stats.tx_unicast_count++;
+        netif->stats.tx_unicast_count++;
     }
 #endif
 #ifdef MODULE_GNRC_MAC