diff --git a/Makefile.dep b/Makefile.dep
index e083323e1b0e67d82efda6c7a4107840c9560b60..cc60f4681d952160e5426d3c4ec30e715306b553 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -445,10 +445,6 @@ ifneq (,$(filter lwip_sock_udp,$(USEMODULE)))
 endif
 
 ifneq (,$(filter lwip_%,$(USEMODULE)))
-  USEMODULE += lwip
-endif
-
-ifneq (,$(filter lwip,$(USEMODULE)))
   USEPKG += lwip
   USEMODULE += core_mbox
   USEMODULE += lwip_api
diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk
index 9a3b4491595463a269aa1c86f1dc227900698ef0..8c13111f20b5677241c17f30422702fe84b9de0c 100644
--- a/makefiles/pseudomodules.inc.mk
+++ b/makefiles/pseudomodules.inc.mk
@@ -36,19 +36,6 @@ PSEUDOMODULES += lis2dh12_spi
 PSEUDOMODULES += log
 PSEUDOMODULES += log_printfnoformat
 PSEUDOMODULES += lora
-PSEUDOMODULES += lwip_arp
-PSEUDOMODULES += lwip_autoip
-PSEUDOMODULES += lwip_dhcp
-PSEUDOMODULES += lwip_ethernet
-PSEUDOMODULES += lwip_igmp
-PSEUDOMODULES += lwip_ipv6_autoconfig
-PSEUDOMODULES += lwip_ipv6_mld
-PSEUDOMODULES += lwip_raw
-PSEUDOMODULES += lwip_sixlowpan
-PSEUDOMODULES += lwip_stats
-PSEUDOMODULES += lwip_tcp
-PSEUDOMODULES += lwip_udp
-PSEUDOMODULES += lwip_udplite
 PSEUDOMODULES += mpu_stack_guard
 PSEUDOMODULES += nanocoap_%
 PSEUDOMODULES += netdev_default
diff --git a/pkg/lwip/Makefile b/pkg/lwip/Makefile
index 04771373009ae6b836774383a004e6df53e66681..379093a031a6cae3b49c0ff035128ba7fe2073c3 100644
--- a/pkg/lwip/Makefile
+++ b/pkg/lwip/Makefile
@@ -1,11 +1,44 @@
 PKG_NAME=lwip
 PKG_URL=git://git.savannah.nongnu.org/lwip.git
-PKG_VERSION=STABLE-2_0_3_RELEASE
+# lwIP v2.1.0
+PKG_VERSION=e6a8415df332ee34d7af02255b2aa1e8ee74348f
 PKG_LICENSE=BSD-3-Clause
 
-.PHONY: all
+LWIP_MODULES         = lwip_api lwip_core lwip_ipv4 lwip_ipv6 \
+                       lwip_netif lwip_netif_ppp lwip_polarssl
+LWIP_USEMODULE       = $(filter $(LWIP_MODULES),$(USEMODULE))
+LWIP_MODULE_MAKEFILE = $(RIOTBASE)/Makefile.base
 
-all: git-download
-	"$(MAKE)" -C $(PKG_BUILDDIR)
+.PHONY: all $(LWIP_MODULES)
+
+CFLAGS += -Wno-address
+
+make_module = "$(MAKE)" -f $(LWIP_MODULE_MAKEFILE) MODULE=$(1) -C $(2)
+
+all: git-download lwip
+
+lwip: $(LWIP_USEMODULE)
+	$(call make_module,$@,$(PKG_BUILDDIR))
+
+lwip_api:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/api)
+
+lwip_core:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/core)
+
+lwip_ipv4:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/core/ipv4)
+
+lwip_ipv6:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/core/ipv6)
+
+lwip_netif:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/netif)
+
+lwip_netif_ppp:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/netif/ppp)
+
+lwip_polarssl:
+	$(call make_module,$@,$(PKG_BUILDDIR)/src/netif/ppp/polarssl)
 
 include $(RIOTBASE)/pkg/pkg.mk
diff --git a/pkg/lwip/Makefile.include b/pkg/lwip/Makefile.include
index 2d6f97bb2ccffa3722c8f3f551dc00124ff47243..a51c7b94dfb472d6b4315d24805ffb0c86577568 100644
--- a/pkg/lwip/Makefile.include
+++ b/pkg/lwip/Makefile.include
@@ -1,6 +1,20 @@
 INCLUDES += -I$(RIOTBASE)/pkg/lwip/include \
             -I$(PKGDIRBASE)/lwip/src/include
 
+PSEUDOMODULES += lwip_arp
+PSEUDOMODULES += lwip_autoip
+PSEUDOMODULES += lwip_dhcp
+PSEUDOMODULES += lwip_ethernet
+PSEUDOMODULES += lwip_igmp
+PSEUDOMODULES += lwip_ipv6_autoconfig
+PSEUDOMODULES += lwip_ipv6_mld
+PSEUDOMODULES += lwip_raw
+PSEUDOMODULES += lwip_sixlowpan
+PSEUDOMODULES += lwip_stats
+PSEUDOMODULES += lwip_tcp
+PSEUDOMODULES += lwip_udp
+PSEUDOMODULES += lwip_udplite
+
 ifneq (,$(filter lwip_contrib,$(USEMODULE)))
   DIRS += $(RIOTBASE)/pkg/lwip/contrib
 endif
diff --git a/pkg/lwip/contrib/netdev/lwip_netdev.c b/pkg/lwip/contrib/netdev/lwip_netdev.c
index 14aa6d751e0b6f66a3161d9960ec8a97aa679500..73ec8190c658449e2406dbfc2b342df6e9d6c8ad 100644
--- a/pkg/lwip/contrib/netdev/lwip_netdev.c
+++ b/pkg/lwip/contrib/netdev/lwip_netdev.c
@@ -131,7 +131,7 @@ err_t lwip_netdev_init(struct netif *netif)
         case NETDEV_TYPE_IEEE802154:
         {
             u16_t val;
-            ipv6_addr_t *addr;
+            ip6_addr_t *addr;
             if (netdev->driver->get(netdev, NETOPT_NID, &val,
                                     sizeof(val)) < 0) {
                 return ERR_IF;
@@ -154,11 +154,13 @@ err_t lwip_netdev_init(struct netif *netif)
             }
             /* netif_create_ip6_linklocal_address() does weird byte-swapping
              * with full IIDs, so let's do it ourselves */
-            addr = (ipv6_addr_t *)&(netif->ip6_addr[0]);
-            if (netdev->driver->get(netdev, NETOPT_IPV6_IID, &addr->u8[8], sizeof(eui64_t)) < 0) {
+            addr = &(netif->ip6_addr[0]);
+            /* addr->addr is a uint32_t array */
+            if (netdev->driver->get(netdev, NETOPT_IPV6_IID, &addr->addr[2], sizeof(eui64_t)) < 0) {
                 return ERR_IF;
             }
-            ipv6_addr_set_link_local_prefix(addr);
+            ipv6_addr_set_link_local_prefix((ipv6_addr_t *)&addr->addr[0]);
+            ip6_addr_assign_zone(addr, IP6_UNICAST, netif);
             /* Set address state. */
 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
             /* Will perform duplicate address detection (DAD). */
diff --git a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c
index 0a8d6b32f6dbe830783e3497480b29fae48978a8..fde43b4d434e24ebb03659350a9887afbefef301 100644
--- a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c
+++ b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c
@@ -92,7 +92,7 @@ static uint16_t _ip6_addr_to_netif(const ip6_addr_p_t *_addr)
     ip6_addr_t addr;
 
     assert(_addr != NULL);
-    ip6_addr_copy(addr, *_addr);
+    ip6_addr_copy_from_packed(addr, *_addr);
     if (!ip6_addr_isany_val(addr)) {
         for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
             if (netif_get_ip6_addr_match(netif, &addr) >= 0) {
diff --git a/pkg/lwip/contrib/sock/lwip_sock.c b/pkg/lwip/contrib/sock/lwip_sock.c
index dba775c17d9375a8676fe9afd24a5199d7faa1dd..40b4a10305f0d546948af450417053174531f5d9 100644
--- a/pkg/lwip/contrib/sock/lwip_sock.c
+++ b/pkg/lwip/contrib/sock/lwip_sock.c
@@ -151,6 +151,23 @@ static bool _addr_on_netif(int family, int netif_num, const ip_addr_t *addr)
     p = (ep)->port;
 #endif
 
+static void _convert_ip_addr(ip_addr_t *lwip_addr, int family,
+                             const void *sock_addr, size_t sock_addr_size)
+{
+    memcpy(lwip_addr, sock_addr, sock_addr_size);
+#if LWIP_IPV6 && LWIP_IPV4
+    if (family == AF_INET6) {
+        ip6_addr_clear_zone(&lwip_addr->u_addr.ip6);
+    }
+    lwip_addr->type = lwip_af_to_ip_addr_type(family);
+#elif LWIP_IPV6
+    (void)family;
+    ip6_addr_clear_zone(lwip_addr);
+#else
+    (void)family;
+#endif
+}
+
 static int _sock_ep_to_netconn_pars(const struct _sock_tl_ep *local,
                                     const struct _sock_tl_ep *remote,
                                     ip_addr_t *local_addr, u16_t *local_port,
@@ -193,10 +210,8 @@ static int _sock_ep_to_netconn_pars(const struct _sock_tl_ep *local,
             netif = remote->netif;
         }
         family = remote->family;
-        memcpy(remote_addr, &remote->addr, sizeof(remote->addr));
-#if LWIP_IPV6 && LWIP_IPV4
-        remote_addr->type = lwip_af_to_ip_addr_type(family);
-#endif
+        _convert_ip_addr(remote_addr, family, &remote->addr,
+                         sizeof(remote->addr));
         if (ip_addr_isany(remote_addr)) {
             return -EINVAL;
         }
@@ -224,7 +239,8 @@ static int _sock_ep_to_netconn_pars(const struct _sock_tl_ep *local,
         /* case (local == NULL) is included in _ep_isany() */
         /* cast to ip_addr_t alright, since type field is never used */
         else if (_addr_on_netif(family, netif, (ip_addr_t *)&local->addr)) {
-            memcpy(local_addr, &local->addr, sizeof(local->addr));
+            _convert_ip_addr(local_addr, family, &local->addr,
+                             sizeof(local->addr));
             res = 1;
         }
         else {
@@ -232,14 +248,9 @@ static int _sock_ep_to_netconn_pars(const struct _sock_tl_ep *local,
         }
     }
     else if (local != NULL) {
-        memcpy(local_addr, &local->addr, sizeof(local->addr));
+        _convert_ip_addr(local_addr, family, &local->addr, sizeof(local->addr));
         res = 1;
     }
-#if LWIP_IPV6 && LWIP_IPV4
-    if (local_addr != NULL) {
-        local_addr->type = lwip_af_to_ip_addr_type(family);
-    }
-#endif
 
     return res;
 }
diff --git a/pkg/lwip/patches/0001-Fix-warnings.patch b/pkg/lwip/patches/0001-Fix-warnings.patch
deleted file mode 100644
index c90f306ba72ebeebda08e245e705f1de5a13594c..0000000000000000000000000000000000000000
Binary files a/pkg/lwip/patches/0001-Fix-warnings.patch and /dev/null differ
diff --git a/pkg/lwip/patches/0001-lowpan6.c-Fix-IEEE-802.15.4-address-setting.patch b/pkg/lwip/patches/0001-lowpan6.c-Fix-IEEE-802.15.4-address-setting.patch
new file mode 100644
index 0000000000000000000000000000000000000000..793da70f4e9d7068b4c89c5042ba94b50e27bff4
Binary files /dev/null and b/pkg/lwip/patches/0001-lowpan6.c-Fix-IEEE-802.15.4-address-setting.patch differ
diff --git a/pkg/lwip/patches/0002-Add-RIOT-Makefiles.patch b/pkg/lwip/patches/0002-Add-RIOT-Makefiles.patch
deleted file mode 100644
index d6e0000b72d9f96bc7d152fb5b40c34b9a10931d..0000000000000000000000000000000000000000
Binary files a/pkg/lwip/patches/0002-Add-RIOT-Makefiles.patch and /dev/null differ
diff --git a/tests/lwip_sock_ip/stack.c b/tests/lwip_sock_ip/stack.c
index e4c91671eb7bc55bed884a68b25757fba4b18f1f..7dfd18879e27b8409038222c114ab8b7e3ab4894 100644
--- a/tests/lwip_sock_ip/stack.c
+++ b/tests/lwip_sock_ip/stack.c
@@ -235,6 +235,8 @@ void _prepare_send_checks(void)
         if (nc->state == ND6_NO_ENTRY) {
             nc->state = ND6_REACHABLE;
             memcpy(&nc->next_hop_address, remote6, sizeof(ip6_addr_t));
+            ip6_addr_assign_zone(&nc->next_hop_address,
+                                 IP6_UNICAST, &netif);
             memcpy(&nc->lladdr, mac, 6);
             nc->netif = &netif;
             nc->counter.reachable_time = UINT32_MAX;
diff --git a/tests/lwip_sock_tcp/Makefile b/tests/lwip_sock_tcp/Makefile
index f14f9456176bd13d9b8ee04bfc2594604ed98803..499e61386eb02a4b2985855735ea6b9f0d2f244f 100644
--- a/tests/lwip_sock_tcp/Makefile
+++ b/tests/lwip_sock_tcp/Makefile
@@ -5,7 +5,8 @@ include ../Makefile.tests_common
 BOARD_BLACKLIST := arduino-uno arduino-duemilanove arduino-mega2560 chronos \
                    msb-430 msb-430h telosb waspmote-pro wsn430-v1_3b \
                    wsn430-v1_4 z1 jiminy-mega256rfr2 mega-xplained
-BOARD_INSUFFICIENT_MEMORY = nucleo-f031k6 nucleo-f042k6 nucleo-l031k6 nucleo-f030r8 \
+BOARD_INSUFFICIENT_MEMORY = blackpill bluepill nucleo-f031k6 nucleo-f042k6 \
+                            nucleo-l031k6 nucleo-f030r8 nucleo-f302r8 \
                             nucleo-f303k8 nucleo-f334r8 nucleo-l053r8 \
                             stm32f0discovery
 
diff --git a/tests/lwip_sock_udp/stack.c b/tests/lwip_sock_udp/stack.c
index 4ac890b6e337575f90ceb25f4eca97a255d9e09d..d4a08c43af9b30f60ae93bed1ca6a815eac3b918 100644
--- a/tests/lwip_sock_udp/stack.c
+++ b/tests/lwip_sock_udp/stack.c
@@ -39,7 +39,7 @@
 #include "constants.h"
 #include "stack.h"
 
-#define _MSG_QUEUE_SIZE         (1)
+#define _MSG_QUEUE_SIZE         (4)
 #define _SEND_DONE              (0x92d7)
 #define _NETDEV_BUFFER_SIZE     (128)
 
@@ -237,6 +237,8 @@ void _prepare_send_checks(void)
         if (nc->state == ND6_NO_ENTRY) {
             nc->state = ND6_REACHABLE;
             memcpy(&nc->next_hop_address, remote6, sizeof(ip6_addr_t));
+            ip6_addr_assign_zone(&nc->next_hop_address,
+                                 IP6_UNICAST, &netif);
             memcpy(&nc->lladdr, mac, 6);
             nc->netif = &netif;
             nc->counter.reachable_time = UINT32_MAX;