[PATCH v3 1/2] STM32 lwIP addition

Robin Mueller robin.mueller.m at gmail.com
Sun Oct 24 10:54:06 UTC 2021


This patch adds the STM32H7 / NUCLEO-H743ZI lwIP port.
It also improves the architecture to make integration
of new BSPs easier. The patch continues the wscript file to
allow installing the lwIP support similar to how a RTEMS
BSP is installed.

https://github.com/rmspacefish/rtems-stm32-lwip is a self-contained
repository to test the lwIP integration for the arm/stm32h7
and arm/nucleo-h743zi BSP. The repository README specifies
how to build the RTEMS lwIP support and install it at a specified
prefix location.

The STM32 port includes the LAN driver (lan8742.c). All other
required code is added in form of a patch file.

The common source file were refactored to be more generic and independent
of the used BSP.

This patch includes corrections from the code review by Gedare Bloom.

Some licensing issues with code provided by STM were resolved by requiring users
to apply a patch file for now.

The LwIP version was updated to v2.1.3
---
 .gitignore                                    |   6 +
 .gitmodules                                   |   1 +
 README.md                                     |  32 +
 lwip-upstream                                 |   2 +-
 lwip.py                                       | 182 ++++-
 .../drivers/{eth_lwip.c => rtems_lwip.c}      | 187 +++--
 .../drivers/{eth_lwip.h => rtems_lwip.h}      |  92 ++-
 .../{eth_lwip_default.h => rtems_lwip_conf.h} |  30 +-
 lwip/ports/drivers/stm32h7/lan8742.c          | 664 ++++++++++++++++++
 lwip/ports/drivers/stm32h7/lan8742.h          | 448 ++++++++++++
 lwip/ports/drivers/stm32h7/port_conf.h        |  44 ++
 .../stm32h7/template/lwipopts_template.h      | 292 ++++++++
 .../include/rtems_lwip}/tms570_netif.h        |  31 +
 .../ports/drivers/{ => tms570}/phy_dp83848h.c |   0
 .../ports/drivers/{ => tms570}/phy_dp83848h.h |   0
 .../tms570/template/lwipopts_template.h       |  75 ++
 lwip/ports/drivers/{ => tms570}/ti_drv_emac.h |   0
 lwip/ports/drivers/{ => tms570}/ti_drv_mdio.h |   0
 lwip/ports/drivers/{ => tms570}/tms570_emac.h |   0
 .../ports/drivers/{ => tms570}/tms570_netif.c |  11 +-
 lwip/ports/os/rtems/arch/cc.h                 |   3 +
 lwip/ports/os/rtems/arch/sys_arch.c           |  31 +-
 lwip/ports/os/rtems/arch/sys_arch.h           |  18 +-
 lwip/ports/os/rtems/defaults/lwipopts.h       |  37 +
 lwip/src/api/api_lib.c                        |   8 +-
 lwip/src/api/api_msg.c                        |   5 +-
 lwip/src/api/netdb.c                          |  40 --
 lwip/src/api/sockets.c                        |  15 +-
 lwip/src/api/tcpip.c                          |   2 +-
 lwip/src/core/altcp.c                         |  36 +
 lwip/src/core/altcp_tcp.c                     |  30 +
 lwip/src/core/init.c                          |   5 +-
 lwip/src/core/ipv4/dhcp.c                     |  43 +-
 lwip/src/core/ipv4/icmp.c                     |  18 +-
 lwip/src/core/ipv6/dhcp6.c                    |  13 +-
 lwip/src/core/ipv6/icmp6.c                    |  27 +-
 lwip/src/core/ipv6/mld6.c                     |   4 +-
 lwip/src/core/ipv6/nd6.c                      |  30 +-
 lwip/src/core/netif.c                         |  46 +-
 lwip/src/core/pbuf.c                          |  58 +-
 lwip/src/core/tcp.c                           |   4 +
 lwip/src/core/tcp_in.c                        |   5 +-
 lwip/src/core/tcp_out.c                       |   7 +-
 lwip/src/core/udp.c                           |  12 +-
 lwip/src/include/lwip/altcp.h                 |   5 +
 lwip/src/include/lwip/altcp_tls.h             |  28 +-
 .../lwip/apps/altcp_tls_mbedtls_opts.h        |  42 +-
 lwip/src/include/lwip/apps/sntp.h             |   6 +-
 lwip/src/include/lwip/apps/sntp_opts.h        |   6 +
 lwip/src/include/lwip/debug.h                 |   4 +-
 lwip/src/include/lwip/if_api.h                |   2 +
 lwip/src/include/lwip/init.h                  |   4 +-
 lwip/src/include/lwip/netdb.h                 |  65 +-
 lwip/src/include/lwip/netif.h                 |   6 +-
 lwip/src/include/lwip/opt.h                   |  25 +-
 lwip/src/include/lwip/pbuf.h                  |   4 +
 lwip/src/include/lwip/priv/altcp_priv.h       |  13 +
 lwip/src/include/lwip/prot/icmp6.h            |   2 +
 lwip/src/include/lwip/prot/ip6.h              |   2 +
 lwip/src/include/lwip/sys.h                   |   1 -
 lwip/src/include/netif/ppp/ppp_opts.h         |   7 +
 lwip/src/include/netif/ppp/pppoe.h            |   8 +-
 lwip/src/netif/ethernet.c                     |   2 +-
 lwip/src/netif/lowpan6.c                      |   2 +-
 lwip/src/netif/lowpan6_ble.c                  |   2 +-
 lwip/src/netif/lowpan6_common.c               |   8 +-
 lwip/src/netif/ppp/pppoe.c                    |  43 +-
 lwip/src/netif/zepif.c                        |   2 +-
 lwip/{ports/os => test}/lwipopts.h            |   0
 wscript                                       |   2 +
 70 files changed, 2475 insertions(+), 410 deletions(-)
 create mode 100644 README.md
 rename lwip/ports/drivers/{eth_lwip.c => rtems_lwip.c} (56%)
 rename lwip/ports/drivers/{eth_lwip.h => rtems_lwip.h} (55%)
 rename lwip/ports/drivers/{eth_lwip_default.h => rtems_lwip_conf.h} (68%)
 create mode 100644 lwip/ports/drivers/stm32h7/lan8742.c
 create mode 100644 lwip/ports/drivers/stm32h7/lan8742.h
 create mode 100644 lwip/ports/drivers/stm32h7/port_conf.h
 create mode 100644 lwip/ports/drivers/stm32h7/template/lwipopts_template.h
 rename lwip/ports/drivers/{ => tms570/include/rtems_lwip}/tms570_netif.h (74%)
 rename lwip/ports/drivers/{ => tms570}/phy_dp83848h.c (100%)
 rename lwip/ports/drivers/{ => tms570}/phy_dp83848h.h (100%)
 create mode 100644 lwip/ports/drivers/tms570/template/lwipopts_template.h
 rename lwip/ports/drivers/{ => tms570}/ti_drv_emac.h (100%)
 rename lwip/ports/drivers/{ => tms570}/ti_drv_mdio.h (100%)
 rename lwip/ports/drivers/{ => tms570}/tms570_emac.h (100%)
 rename lwip/ports/drivers/{ => tms570}/tms570_netif.c (99%)
 create mode 100644 lwip/ports/os/rtems/defaults/lwipopts.h
 rename lwip/{ports/os => test}/lwipopts.h (100%)

diff --git a/.gitignore b/.gitignore
index 618d791..91a3a03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,10 @@
+# Python
 __pycache__
+
+# Waf
 .lock-waf*
 .waf*
+/*.pyc
+
+# Builds
 build/
diff --git a/.gitmodules b/.gitmodules
index 4ea46da..a98aac6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,4 @@
 [submodule "rtems_waf"]
 	path = rtems_waf
 	url = git://git.rtems.org/rtems_waf.git
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ebbef12
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+RTEMS lwIP Repository
+======
+
+This repository contains the RTEMS lwIP support and all available ports.
+Currently, the following RTEMS BSPs are supported:
+
+ - All `arm/tms*` BSPs.
+ - The `arm/stm32h7` and the `arm/nucleo-h743zi` BSP. An example application can be
+   found [here](https://github.com/rmspacefish/rtems-stm32-lwip).
+
+# Using this repository
+
+The repository contains the lwIP sources, the OS port for RTEMS and port files
+belonging to a RTEMS BSP.
+
+It is recommended that the user supplies the `lwipopts.h` configuration file. The port folders
+contain template option files to get started. The user can copy and rename this files into the
+application and then pass the include path to the build system using the `--lwip-opts` option.
+
+# Building with waf
+
+It is assumed that the path(s) containing the `lwipopts.h` file was stored in the environmental
+variable `LWIP_OPTS_PATH`, the install prefix is stored in the environmental
+variable `RTEMS_PREFIX` and the RTEMS BSP is stored inside `RTEMS_BSP`.
+The lwIP support can now be built like this:
+
+```sh
+./waf configure --prefix="$RTEMS_PREFIX" --lwip-opts="$LWIP_OPTS_PATH" --rtems-bsp="$RTEMS_BSP"
+./waf
+./waf install
+```
+
diff --git a/lwip-upstream b/lwip-upstream
index 159e31b..ed6c951 160000
--- a/lwip-upstream
+++ b/lwip-upstream
@@ -1 +1 @@
-Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10
+Subproject commit ed6c951a19659ba81e8860cd1ee55ba4ee93d356
diff --git a/lwip.py b/lwip.py
index a3eb7cb..56919d9 100644
--- a/lwip.py
+++ b/lwip.py
@@ -33,45 +33,163 @@ source_files = []
 driver_source = []
 include_files = {}
 
+DEFAULT_OPTIONS_PATH = "./lwip/ports/os/rtems/defaults"
+DEBUG_LWIP_WSCRIPT = False
+BUILD_SAMPLE_FILE = False
+RTEMS_LWIP_PORT_INC_FOLDER_NAME = "rtems_lwip"
+
+
+
+def options(opt):
+    opt.add_option(
+        "--lwip-opts",
+        default=DEFAULT_OPTIONS_PATH,
+        dest="lwipopts_path",
+        help="Path including the lwipopts.h file. If none is supplied, a default "
+             " configuration file will be used"
+    )
+
+
+def configure(conf):
+    conf.env.LWIPOPTS_PATH = conf.options.lwipopts_path
+    if(conf.env.LWIPOPTS_PATH == DEFAULT_OPTIONS_PATH):
+        print('No path for lwipopts.h file supplied, using default path %s' % DEFAULT_OPTIONS_PATH)
+    else:
+        print('Path(s) for lwIP options supplied: %s' % conf.env.LWIPOPTS_PATH)
+
+
 def build(bld):
-    arch_lib_path = rtems.arch_bsp_lib_path(bld.env.RTEMS_VERSION,
-                                            bld.env.RTEMS_ARCH_BSP)
+    arch_lib_path = rtems.arch_bsp_lib_path(
+        bld.env.RTEMS_VERSION, bld.env.RTEMS_ARCH_BSP
+    )
+    arch_inc_path = rtems.arch_bsp_include_path(
+        bld.env.RTEMS_VERSION, bld.env.RTEMS_ARCH_BSP
+    )
+
     with open('file-import.yaml', 'r') as cf:
         files = yaml.full_load(cf.read())
         for f in files['files-to-import']:
             if f[-2:] == '.c':
                 source_files.append(os.path.join('./lwip', f))
-        
-        for f in os.listdir('./lwip/ports/drivers'):
+
+    # Determine port sources and include path, if there are any
+    port_name = ""
+    generic_port_path = './lwip/ports/drivers'
+    if bld.env.RTEMS_BSP in ["nucleo-h743zi", "stm32h7"]:
+        port_name = "stm32h7"
+    elif "tms570" in bld.env.RTEMS_BSP:
+        port_name = "tms570"
+    driver_include_path = ""
+    if port_name != "":
+        port_path = './lwip/ports/drivers/%s' % port_name
+        driver_include_path = os.path.join(
+            port_path, 'include/%s' % RTEMS_LWIP_PORT_INC_FOLDER_NAME
+        )
+        for f in os.listdir(port_path):
             if f[-2:] == '.c':
-                driver_source.append(os.path.join('./lwip/ports/drivers', f))
+                driver_source.append(os.path.join(port_path, f))
+    else:
+        print("Port does not exist. Only compiling lwIP source files")
+
+    if DEBUG_LWIP_WSCRIPT:
+        print('Port sources: ')
+        print(driver_source)
+
+    os_inc_path = './lwip/ports/os/rtems/arch'
+
     source_files.append('./lwip/ports/os/rtems/arch/sys_arch.c')
-    
-    #source_files.append('./lwip/ports/port/sys_arch.c')
-    #source_files.append('./lwip/ports/port/perf.c')
-    #source_files.append('./lwip/ports/port/netif/fifo.c')
-    #source_files.append('./lwip/ports/port/netif/list.c')
-    #source_files.append('./lwip/ports/port/netif/pcapif.c')
-    #source_files.append('./lwip/ports/port/netif/sio.c')
-    #source_files.append('./lwip/ports/port/netif/tapif.c')
-
-    bld(features ='c',
+    source_files.append('./lwip/ports/drivers/rtems_lwip.c')
+    source_files.append(driver_source)
+
+    # Add the path containing the lwipopts.h file
+    options_include_path = bld.env.LWIPOPTS_PATH
+
+    if(options_include_path == ""):
+      print("Invalid options path, setting default path")
+      options_include_path = DEFAULT_OPTIONS_PATH
+
+    lwip_core_include_path = './lwip/src/include'
+    lwip_obj_includes = \
+        './include %s ./lwip/src/include lwip/ports/port/include ./lwip/ports/os ' \
+        './lwip/ports/drivers ./lwip/ports/os/rtems %s %s' \
+        % (lwip_core_include_path, options_include_path, driver_include_path)
+
+    if DEBUG_LWIP_WSCRIPT:
+        print('Include paths for lwIP: ')
+        print(lwip_obj_includes)
+
+    bld(
+        features='c',
         target='lwip_obj',
-        includes='./include ./lwip/src/include lwip/ports/port/include ./lwip/ports/os ./lwip/ports/drivers ./lwip/ports/os/rtems',
-        source=source_files,
+        includes=lwip_obj_includes,
+        source=source_files
+    )
+
+    bld(
+        features='c cstlib',
+        target='lwip',
+        use=['lwip_obj']
+     )
+
+    # Install static library
+    bld.install_files(os.path.join('${PREFIX}', arch_lib_path), ["liblwip.a"])
+
+    install_header_source = []
+    install_header_target = []
+
+    # Installation for the lwIP core header files
+    for root, dirnames, filenames in os.walk(lwip_core_include_path):
+        install_headers_source = [
+            os.path.join(root, file)
+            for file in filenames
+            if (file[-2:] == '.h')
+        ]
+        install_headers_target = os.path.relpath(root, lwip_core_include_path)
+        install_destination = os.path.join(bld.env.PREFIX, arch_inc_path, install_headers_target)
+        if DEBUG_LWIP_WSCRIPT:
+            print('Install Source: %s' % install_headers_source)
+        if DEBUG_LWIP_WSCRIPT:
+            print('Install Target: %s' % install_destination)
+        bld.install_files(install_destination, install_headers_source)
+
+    # Installation for the lwIP port header files
+    generic_port_include_files = os.listdir(generic_port_path)
+    install_headers_source = [
+        os.path.join(generic_port_path, file)
+        for file in generic_port_include_files
+        if (file[-2:] == '.h')
+    ]
+    if driver_include_path != "":
+        drv_include_files = os.listdir(driver_include_path)
+        install_headers_source += [
+            os.path.join(driver_include_path, file)
+            for file in drv_include_files
+            if (file[-2:] == '.h')
+        ]
+        install_destination = os.path.join(bld.env.PREFIX, arch_inc_path, 'rtems_lwip')
+        bld.install_files(install_destination, install_headers_source)
+
+    # Installation for OS abstraction layer
+    os_include_files = os.listdir(os_inc_path)
+    install_headers_source = [
+        os.path.join(os_inc_path, file)
+        for file in os_include_files
+        if (file[-2:] == '.h')
+    ]
+    install_destination = os.path.join(bld.env.PREFIX, arch_inc_path, 'arch')
+    bld.install_files(install_destination,  install_headers_source)
+
+    if BUILD_SAMPLE_FILE:
+        sample_inc = \
+            './include ./lwip/ports/os/rtems ./lwip/ports/os ./lwip/src/include ' \
+            './lwip/ports/os/rtems ./lwip/test/' \
+            + os.path.relpath(os.path.join(arch_lib_path,'include'))
+        bld.program(
+            features='c',
+            target='test01.exe',
+            source='./lwip/test/sample_app.c',
+            use='lwip',
+            lib=['rtemscpu', 'rtemsbsp', 'rtemstest', 'lwip'],
+            includes=sample_inc
         )
-#    bld(features ='c',
-#        target='lwip_drv_obj',
-#        includes='./ ../ ../../src/include ./include ./lwip/src/include ./lwip/ports/os/rtems ./lwip/ports/os ./lwip/ports/drivers ' + os.path.relpath(os.path.join(arch_lib_path,'include')),
-#        source=driver_source,
-#        )
-    bld(features='c cstlib',
-        target = 'lwip',
-        use=['lwip_obj'])
-
-    bld.program(features='c',
-                target='test01.exe',
-                source='./lwip/test/sample_app.c',
-                use='lwip',
-                lib=['rtemscpu', 'rtemsbsp', 'rtemstest', 'lwip'],
-                includes='./include ./lwip/ports/os/rtems ./lwip/ports/os ./lwip/src/include ./lwip/ports/os/rtems ./lwip/test/' + os.path.relpath(os.path.join(arch_lib_path,'include')))
+
diff --git a/lwip/ports/drivers/eth_lwip.c b/lwip/ports/drivers/rtems_lwip.c
similarity index 56%
rename from lwip/ports/drivers/eth_lwip.c
rename to lwip/ports/drivers/rtems_lwip.c
index b1ae4bb..0633605 100644
--- a/lwip/ports/drivers/eth_lwip.c
+++ b/lwip/ports/drivers/rtems_lwip.c
@@ -31,53 +31,47 @@
  * Based on work of Carlos Jenkins, Rostislav Lisovy, Jan Dolezal
  */
 
-//#define DEBUG 1
-#include "lwip/tcpip.h" /* includes - lwip/opt.h, lwip/api_msg.h, lwip/netifapi.h, lwip/pbuf.h, lwip/api.h, lwip/sys.h, lwip/timers.h, lwip/netif.h */
+#include "rtems_lwip.h"
+#include "rtems_lwip_conf.h"
+
+#include "lwip/init.h"
 #include "lwip/stats.h"
 #include "lwip/dhcp.h"
+#include "netif/ethernet.h"
+
+#if LWIP_NETIF_API == 1
 #include "lwip/netifapi.h"
-#include "netif/etharp.h" /* includes - lwip/ip.h, lwip/netif.h, lwip/ip_addr.h, lwip/pbuf.h */
-#include "eth_lwip_default.h"
-#include "eth_lwip.h"
-#include "tms570_netif.h"
-#include <stdio.h>
+#endif
 
-/* The lwIP network interface structure for the Ethernet EMAC. */
-#ifndef MAX_EMAC_INSTANCE
-#define MAX_EMAC_INSTANCE           1
-#endif /*MAX_EMAC_INSTANCE*/
+#if NO_SYS == 0
+#include "lwip/tcpip.h"
+#endif
+
+#include <stdio.h>
 
 #define SUCCESS ERR_OK
 #define FAILURE ERR_IF
 
-static struct netif eth_lwip_netifs[MAX_EMAC_INSTANCE];
-static void eth_lwip_conv_IP_decimal_Str(ip_addr_t ip, uint8_t *ipStr);
+/* Assigned in specific port */
+extern netif_init_fn eth_lwip_init_fnc;
 
+/* The lwIP network interface structure for the Ethernet EMAC. */
+#ifndef MAX_EMAC_INSTANCE
+#define MAX_EMAC_INSTANCE           1
+#endif /*MAX_EMAC_INSTANCE*/
 
-void
-eth_lwip_get_dhcp_info(void)
-{
-  struct netif *netif = eth_lwip_get_netif(0);
-
-  if (dhcp_supplied_address(netif)) {
-    uint8_t ipString[16]; // FIXME change the functions to use char
-    eth_lwip_conv_IP_decimal_Str(netif->ip_addr, ipString);
-    printf("Address: %s\n", ipString);
-    eth_lwip_conv_IP_decimal_Str(netif->netmask, ipString);
-    printf("Netmask: %s\n", ipString);
-    eth_lwip_conv_IP_decimal_Str(netif->gw, ipString);
-    printf("Gateway: %s\n", ipString);
-  } else {
-    printf("dhcp not bound\n");
-  }
-}
+struct netif eth_lwip_netifs[MAX_EMAC_INSTANCE];
 
 int8_t
-eth_lwip_init(uint8_t *mac_addr)
+rtems_lwip_init(uint8_t *mac_addr, netif_status_callback_fn netif_status_cb)
 {
   unsigned int instance_number = 0;
-  int8_t retVal = SUCCESS;
+  int8_t retval = SUCCESS;
 
+#if NO_SYS == 1
+  /* Initialize the lwIP stack */
+  lwip_init();
+#endif
 
   ip4_addr_t ip_addr;
   ip4_addr_t net_mask;
@@ -89,63 +83,78 @@ eth_lwip_init(uint8_t *mac_addr)
   if (mac_addr == NULL)
     mac_addr = default_mac;             /* use default MAC */
 
-  eth_lwip_set_hwaddr(netif, mac_addr);
+  rtems_lwip_set_hwaddr(netif, mac_addr);
+
+#if NO_SYS == 0
   tcpip_init(NULL, NULL);
+#endif
 
-#if STATIC_IP_ADDRESS
-  ip_addr.addr = htonl(ETH_IP_ADDR);
-  net_mask.addr = htonl(ETH_NETMASK);
-  gw_addr.addr = htonl(ETH_GW);
+  rtems_lwip_determine_static_ipv4_address(&ip_addr, &net_mask, &gw_addr);
+
+  netif_input_fn netif_input_fnc = NULL;
+#if NO_SYS == 1
+  netif_input_fnc = &ethernet_input;
 #else
-  ip_addr.addr = 0;
-  net_mask.addr = 0;
-  gw_addr.addr = 0;
+  netif_input_fnc = &tcpip_input;
 #endif
 
   netif_tmp = netif_add(netif, &ip_addr, &net_mask, &gw_addr,
-                        NULL, ETH_LWIP_INIT_NETIF_FNC, tcpip_input);
+                        NULL, eth_lwip_init_fnc, netif_input_fnc);
 
   if (netif_tmp == NULL)
     return NETIF_ADD_ERR;
 
   netif_set_default(netif);
+
+#if LWIP_NETIF_API == 1
   netifapi_netif_set_up(netif);
-#if !STATIC_IP_ADDRESS
+#endif
+
+#if LWIP_NETIF_LINK_CALLBACK
+  if(netif_status_cb != NULL) {
+    netif_status_cb(netif);
+    netif_set_link_callback(netif, netif_status_cb);
+  }
+#endif
+
+#if !STATIC_IP_ADDRESS && NO_SYS == 0 && LWIP_NETIF_API == 1
   netifapi_dhcp_start(netif);
 #endif
 
-  return retVal;
+  return retval;
+}
+
+void
+rtems_lwip_print_dhcp_info(void)
+{
+  struct netif *netif = rtems_lwip_get_netif(0);
+
+  if (dhcp_supplied_address(netif)) {
+    printf("DHCP information: \n\r");
+    printf("Address: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
+    printf("Netmask: %s\n\r", ip4addr_ntoa(netif_ip4_netmask(netif)));
+    printf("Gateway: %s\n\r", ip4addr_ntoa(netif_ip4_gw(netif)));
+  } else {
+    printf("DHCP not bound\n\r");
+  }
 }
 
 int
-eth_lwip_get_netif_status_cmd(int argc, char *arg[])
+rtems_lwip_get_netif_status_cmd(int argc, char *arg[])
 {
   stats_display();
   return 0;
 }
 
 struct netif *
-eth_lwip_get_netif(uint32_t instance_number)
+rtems_lwip_get_netif(uint32_t instance_number)
 {
-  if (instance_number >= MAX_EMAC_INSTANCE)
+  if (instance_number >= MAX_EMAC_INSTANCE) {
     return NULL;
+  }
   return &eth_lwip_netifs[instance_number];
 }
 
-static void
-eth_lwip_conv_IP_decimal_Str(ip_addr_t ip, uint8_t *ipStr)
-{
-  uint32_t addr;
- #if LWIP_IPV6
-  addr = ip.u_addr.ip4.addr;
- #else
-  addr = ip.addr;
- #endif
-
-  snprintf((char *)ipStr, 16, "%lu.%lu.%lu.%lu",
-           (addr >> 24), ((addr >> 16) & 0xff), ((addr >> 8) & 0xff), (addr & 0xff));
-}
-
 /*
 * Function to set the MAC address to the interface
 * @param   inst_num the instance number
@@ -153,7 +162,7 @@ eth_lwip_conv_IP_decimal_Str(ip_addr_t ip, uint8_t *ipStr)
 * @note    mac_addr[0] is considered MSB
 */
 void
-eth_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr)
+rtems_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr)
 {
   int i;
 
@@ -171,18 +180,62 @@ eth_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr)
 }
 
 void
-eth_lwip_get_hwaddr_str(struct netif *netif, uint8_t *macStr)
+rtems_lwip_get_hwaddr_str(struct netif *netif, uint8_t *mac_str)
 {
   uint8_t index, outindex = 0;
   char ch;
 
   for (index = 0; index < netif->hwaddr_len; index++) {
-    if (index)
-      macStr[outindex++] = ':';
+    if (index) {
+      mac_str[outindex++] = ':';
+    }
     ch = (netif->hwaddr[index] >> 4);
-    macStr[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
+    mac_str[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
     ch = (netif->hwaddr[index] & 0xf);
-    macStr[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
+    mac_str[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
   }
-  macStr[outindex] = 0;
+  mac_str[outindex] = 0;
+}
+
+void
+rtems_lwip_convert_ip_to_decimal_str(ip_addr_t ip, char *ip_str)
+{
+  uint32_t addr;
+ #if LWIP_IPV6
+  addr = ip.u_addr.ip4.addr;
+ #else
+  addr = ip.addr;
+ #endif
+
+  snprintf((char *)ip_str, 16, "%lu.%lu.%lu.%lu",
+           (addr >> 24), ((addr >> 16) & 0xff), ((addr >> 8) & 0xff), (addr & 0xff));
+}
+
+void rtems_lwip_determine_static_ipv4_address(ip4_addr_t* ip_addr, ip4_addr_t* netmask,
+        ip4_addr_t* gw_addr) {
+#if STATIC_IP_ADDRESS == 1
+
+#if CALCULATE_ETH_IP_ADDR == 1
+  IP_ADDR4(ip_addr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+#else
+  ip_addr->addr = htonl(ETH_IP_ADDR);
+#endif
+
+#if CALCULATE_ETH_NETMASK == 1
+  IP_ADDR4(net_mask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+#else
+  net_mask->addr = htonl(ETH_NETMASK);
+#endif
+
+#if CALCULATE_GW_ADDRESS == 1
+  IP_ADDR4(gw_addr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+#else
+  gw_addr->addr = htonl(ETH_GW);
+#endif
+
+#else
+  ip_addr_set_zero_ip4(ip_addr);
+  ip_addr_set_zero_ip4(netmask);
+  ip_addr_set_zero_ip4(gw_addr);
+#endif /* STATIC_IP_ADDRESS == 0 */
 }
diff --git a/lwip/ports/drivers/eth_lwip.h b/lwip/ports/drivers/rtems_lwip.h
similarity index 55%
rename from lwip/ports/drivers/eth_lwip.h
rename to lwip/ports/drivers/rtems_lwip.h
index a9c0325..8802e09 100644
--- a/lwip/ports/drivers/eth_lwip.h
+++ b/lwip/ports/drivers/rtems_lwip.h
@@ -34,67 +34,85 @@
 #ifndef __ETH_LWIP_H
 #define __ETH_LWIP_H
 
+#include "lwip/netif.h"
+#include "rtems_lwip_conf.h"
+
 #include <stdio.h>
 #include <stdbool.h>
-#include "lwip/netif.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /**
- * While scanning phy addresses no alive phy was found.
- * Return value of rpp_eth_hw_init() function.
+ * LwIP netif couldn't be added, it is likely that there was an error during initialization of the hardware.
  */
-#define NO_PHY_ALIVE             -1
+#define NETIF_ADD_ERR            -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
+
 /**
- * Scanning default phy address, it was found it's not alive.
- * Return value of rpp_eth_hw_init() function.
+ * @brief   RTEMS lwIP initialization function.
+ *
+ * Call this method before using this module. This function also takes care of initializing
+ * the lwIP stack by calling lwip_init.
+ * @param   mac_addr            Can be set to NULL to use default mac address
+ * @param   netif_status_cb     Callback function which will be called if the network
+ *                              link status changes
+ * @return
+ *  - SUCCESS if initialization successful.\n
+ *  - NETIF_ADD_ERR Error adding net interface.
  */
-#define DFLT_PHY_NOT_ALIVE       -1
+int8_t rtems_lwip_init(uint8_t *mac_addr, netif_status_callback_fn netif_status_cb);
+
 /**
- * When setting autonegotiation parameters to EMAC module, there was found impossible mode (usually on timeout of autonegotiation).
- * Return value of rpp_eth_hw_init_postInit() function.
+ * @brief   Access to the net interface instances
  */
-#define UNKN_DUPLEX_MODE         -2 /* this could mean that autonegotiation was not completed yet */
+struct netif *rtems_lwip_get_netif(uint32_t instance_number);
+
 /**
- * Phy is down error.
- * Return value of rpp_eth_init_postInit() function.
+ * @brief   Print information about the assigned DHCP address.
  */
-#define PHY_LINK_DOWN            -3
+void rtems_lwip_print_dhcp_info(void);
 
 /**
- * LwIP netif couldn't be added, it is likely that there was an error during initialization of the hardware.
+ * Convert the given IP to its string representation
+ * @param ip
+ * @param ip_str
  */
-#define NETIF_ADD_ERR            -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
+void rtems_lwip_convert_ip_to_decimal_str(ip_addr_t ip, char *ip_str);
+
 /**
- * Memory requirements couldn't be satisfied.
+ * Get the netif status by calling the lwIP  stats_display function
+ * @param argc
+ * @param arg
+ * @return
  */
-#define DHCP_MEM_ERR             -11
+int rtems_lwip_get_netif_status_cmd(int argc, char *arg[]);
 
 /**
- * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
+ * Set the hardware (MAC) address
+ * @param netif
+ * @param mac_addr
  */
-#define MAC_BIG_LETTERS           1
+void rtems_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr);
 
 /**
- * ETH module system startup initialization.
- *
- * Call this method before using this module.
- * This method starts autonegotiation and doesn't check for end of autoneg.
- * When eth module is about to be used, you have to run rpp_eth_init_postInit()
- * first and you should check whether link is up.
- *
- * @return SUCCESS if initialization successful.\n
- *         FAILURE if module already initialized.
+ * Get the hardware (MAC) address
+ * @param netif
+ * @param mac_addr
  */
-int8_t eth_lwip_init(uint8_t *mac_addr);
-void eth_lwip_get_dhcp_info(void);
-int eth_lwip_get_netif_status_cmd(int argc, char *arg[]);
-void eth_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr);
-void eth_lwip_get_hwaddr_str(struct netif *netif, uint8_t *macStr);
-struct netif *eth_lwip_get_netif(uint32_t instance_number);
-
-
-
+void rtems_lwip_get_hwaddr_str(struct netif *netif, uint8_t *mac_str);
 
+/**
+ * @brief   Determines a static IP address from the configuration files.
+ * @param ip_addr
+ * @param netmask
+ * @param gw
+ */
+void rtems_lwip_determine_static_ipv4_address(ip4_addr_t* ip_addr, ip4_addr_t* netmask,
+        ip4_addr_t* gw);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* __ETH_LWIP_H */
diff --git a/lwip/ports/drivers/eth_lwip_default.h b/lwip/ports/drivers/rtems_lwip_conf.h
similarity index 68%
rename from lwip/ports/drivers/eth_lwip_default.h
rename to lwip/ports/drivers/rtems_lwip_conf.h
index 6194d06..85e48f3 100644
--- a/lwip/ports/drivers/eth_lwip_default.h
+++ b/lwip/ports/drivers/rtems_lwip_conf.h
@@ -1,14 +1,8 @@
 #ifndef __ETH_LWIP_DEFAULT_H
 #define __ETH_LWIP_DEFAULT_H
 
-/* #define DEBUG 1 */
-/* #define STATIC_IP_ADDRESS 1 */
-
-void tms570_eth_memp_avaible(int type);
-
-#define ETH_LWIP_INIT_NETIF_FNC tms570_eth_init_netif
-/*called from memp_free() when a memp pool was empty and an item is now available*/
-#define LWIP_HOOK_MEMP_AVAILABLE tms570_eth_memp_avaible
+#include "lwipopts.h"
+#include "lwip/etharp.h"
 
 /* this MAC address is used when user put NULL on the right place when calling postInit function */
 /**
@@ -20,29 +14,43 @@ void tms570_eth_memp_avaible(int type);
 #define ETH_MAC_ADDR             { 0x12 /* Unicast, Locally administered */, 0x34, 0x56, 0x78, 0x9A, 0xBC }
 #endif
 
-#if STATIC_IP_ADDRESS
-
 /**
  * When static IP is configured in lwipopts.h, this IP address is used for interface.
  */
 #ifndef ETH_IP_ADDR
+
+#if defined(IP_ADDR0) && defined(IP_ADDR1) && defined(IP_ADDR2) && defined(IP_ADDR3)
+#define CALCULATE_ETH_IP_ADDR
+#else
 #define ETH_IP_ADDR               0xC0A8F701 /* 192.168.247.1  */
 #endif
 
+#endif
+
 /**
  * When static IP is configured in lwipopts.h, this NETMASK address is used for interface.
  */
 #ifndef ETH_NETMASK
+
+#if defined(NETMASK_ADDR0) && defined(NETMASK_ADDR1) && defined(NETMASK_ADDR2) && defined(NETMASK_ADDR3)
+#define CALCULATE_ETH_NETMASK
+#else
 #define ETH_NETMASK               0xFFFFFF00 /* 255.255.255.0  */
 #endif
 
+#endif
+
 /**
  * When static IP is configured in lwipopts.h, this Gateway address is used for interface.
  */
 #ifndef ETH_GW
+
+#if defined(GW_ADDR0) && defined(GW_ADDR1) && defined(GW_ADDR2) && defined(GW_ADDR3)
+#define CALCULATE_GW_ADDRESS
+#else
 #define ETH_GW                    0xC0A8F7FE /* 192.168.247.254*/
 #endif
 
-#endif /* STATIC_IP_ADDRESS */
+#endif /* ETH_GW */
 
 #endif /* __ETH_LWIP_DEFAULT_H */
diff --git a/lwip/ports/drivers/stm32h7/lan8742.c b/lwip/ports/drivers/stm32h7/lan8742.c
new file mode 100644
index 0000000..a268393
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/lan8742.c
@@ -0,0 +1,664 @@
+/** 
+  ******************************************************************************
+  * @file    lan8742.c
+  * @author  MCD Application Team
+  * @brief   This file provides a set of functions needed to manage the LAN742
+  *          PHY devices.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */  
+
+/* Includes ------------------------------------------------------------------*/
+#include "lan8742.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup Component
+  * @{
+  */ 
+  
+/** @defgroup LAN8742 LAN8742
+  * @{
+  */   
+  
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines
+  * @{
+  */
+#define LAN8742_SW_RESET_TO    ((uint32_t)500U)
+#define LAN8742_INIT_TO        ((uint32_t)2000U)
+#define LAN8742_MAX_DEV_ADDR   ((uint32_t)31U)
+/**
+  * @}
+  */
+ 
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup LAN8742_Private_Functions LAN8742 Private Functions
+  * @{
+  */
+    
+/**
+  * @brief  Register IO functions to component object
+  * @param  pObj: device object  of LAN8742_Object_t. 
+  * @param  ioctx: holds device IO functions.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_ERROR if missing mandatory function
+  */
+int32_t  LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx)
+{
+  if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
+  {
+    return LAN8742_STATUS_ERROR;
+  }
+  
+  pObj->IO.Init = ioctx->Init;
+  pObj->IO.DeInit = ioctx->DeInit;
+  pObj->IO.ReadReg = ioctx->ReadReg;
+  pObj->IO.WriteReg = ioctx->WriteReg;
+  pObj->IO.GetTick = ioctx->GetTick;
+  
+  return LAN8742_STATUS_OK;
+}
+
+/**
+  * @brief  Initialize the lan8742 and configure the needed hardware resources
+  * @param  pObj: device object LAN8742_Object_t. 
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_ADDRESS_ERROR if cannot find device address
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  *         LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset
+  */
+ int32_t LAN8742_Init(lan8742_Object_t *pObj)
+ {
+   uint32_t tickstart = 0, regvalue = 0, addr = 0;
+   int32_t status = LAN8742_STATUS_OK;
+   
+   if(pObj->Is_Initialized == 0)
+   {
+     if(pObj->IO.Init != 0)
+     {
+       /* GPIO and Clocks initialization */
+       pObj->IO.Init();
+     }
+   
+     /* for later check */
+     pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1;
+   
+     /* Get the device address from special mode register */  
+     for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++)
+     {
+       if(pObj->IO.ReadReg(addr, LAN8742_SMR, &regvalue) < 0)
+       { 
+         status = LAN8742_STATUS_READ_ERROR;
+         /* Can't read from this device address 
+            continue with next address */
+         continue;
+       }
+     
+       if((regvalue & LAN8742_SMR_PHY_ADDR) == addr)
+       {
+         pObj->DevAddr = addr;
+         status = LAN8742_STATUS_OK;
+         break;
+       }
+     }
+   
+     if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR)
+     {
+       status = LAN8742_STATUS_ADDRESS_ERROR;
+     }
+     
+     /* if device address is matched */
+     if(status == LAN8742_STATUS_OK)
+     {
+       /* set a software reset  */
+       if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0)
+       { 
+         /* get software reset status */
+         if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) >= 0)
+         { 
+           tickstart = pObj->IO.GetTick();
+           
+           /* wait until software reset is done or timeout occured  */
+           while(regvalue & LAN8742_BCR_SOFT_RESET)
+           {
+             if((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO)
+             {
+               if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) < 0)
+               { 
+                 status = LAN8742_STATUS_READ_ERROR;
+                 break;
+               }
+             }
+             else
+             {
+               status = LAN8742_STATUS_RESET_TIMEOUT;
+               break;
+             }
+           } 
+         }
+         else
+         {
+           status = LAN8742_STATUS_READ_ERROR;
+         }
+       }
+       else
+       {
+         status = LAN8742_STATUS_WRITE_ERROR;
+       }
+     }
+   }
+      
+   if(status == LAN8742_STATUS_OK)
+   {
+     tickstart =  pObj->IO.GetTick();
+     
+     /* Wait for 2s to perform initialization */
+     while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO)
+     {
+     }
+     pObj->Is_Initialized = 1;
+   }
+   
+   return status;
+ }
+
+/**
+  * @brief  De-Initialize the lan8742 and it's hardware resources
+  * @param  pObj: device object LAN8742_Object_t. 
+  * @retval None
+  */
+int32_t LAN8742_DeInit(lan8742_Object_t *pObj)
+{
+  if(pObj->Is_Initialized)
+  {
+    if(pObj->IO.DeInit != 0)
+    {
+      if(pObj->IO.DeInit() < 0)
+      {
+        return LAN8742_STATUS_ERROR;
+      }
+    }
+  
+    pObj->Is_Initialized = 0;  
+  }
+  
+  return LAN8742_STATUS_OK;
+}
+
+/**
+  * @brief  Disable the LAN8742 power down mode.
+  * @param  pObj: device object LAN8742_Object_t.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval &= ~LAN8742_BCR_POWER_DOWN;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Enable the LAN8742 power down mode.
+  * @param  pObj: device object LAN8742_Object_t.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval |= LAN8742_BCR_POWER_DOWN;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Start the auto negotiation process.
+  * @param  pObj: device object LAN8742_Object_t.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval |= LAN8742_BCR_AUTONEGO_EN;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Get the link state of LAN8742 device.
+  * @param  pObj: Pointer to device object. 
+  * @param  pLinkState: Pointer to link state
+  * @retval LAN8742_STATUS_LINK_DOWN  if link is down
+  *         LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed 
+  *         LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
+  *         LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
+  *         LAN8742_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
+  *         LAN8742_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD       
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  
+  /* Read Status register  */
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0)
+  {
+    return LAN8742_STATUS_READ_ERROR;
+  }
+  
+  /* Read Status register again */
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0)
+  {
+    return LAN8742_STATUS_READ_ERROR;
+  }
+  
+  if((readval & LAN8742_BSR_LINK_STATUS) == 0)
+  {
+    /* Return Link Down status */
+    return LAN8742_STATUS_LINK_DOWN;    
+  }
+  
+  /* Check Auto negotiaition */
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0)
+  {
+    return LAN8742_STATUS_READ_ERROR;
+  }
+  
+  if((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN)
+  {
+    if(((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)) 
+    {
+      return LAN8742_STATUS_100MBITS_FULLDUPLEX;
+    }
+    else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT)
+    {
+      return LAN8742_STATUS_100MBITS_HALFDUPLEX;
+    }        
+    else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)
+    {
+      return LAN8742_STATUS_10MBITS_FULLDUPLEX;
+    }
+    else
+    {
+      return LAN8742_STATUS_10MBITS_HALFDUPLEX;
+    }  		
+  }
+  else /* Auto Nego enabled */
+  {
+    if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0)
+    {
+      return LAN8742_STATUS_READ_ERROR;
+    }
+    
+    /* Check if auto nego not done */
+    if((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0)
+    {
+      return LAN8742_STATUS_AUTONEGO_NOTDONE;
+    }
+    
+    if((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD)
+    {
+      return LAN8742_STATUS_100MBITS_FULLDUPLEX;
+    }
+    else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD)
+    {
+      return LAN8742_STATUS_100MBITS_HALFDUPLEX;
+    }
+    else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD)
+    {
+      return LAN8742_STATUS_10MBITS_FULLDUPLEX;
+    }
+    else
+    {
+      return LAN8742_STATUS_10MBITS_HALFDUPLEX;
+    }				
+  }
+}
+
+/**
+  * @brief  Set the link state of LAN8742 device.
+  * @param  pObj: Pointer to device object. 
+  * @param  pLinkState: link state can be one of the following
+  *         LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
+  *         LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
+  *         LAN8742_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
+  *         LAN8742_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD   
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_ERROR  if parameter error  
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState)
+{
+  uint32_t bcrvalue = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &bcrvalue) >= 0)
+  {
+    /* Disable link config (Auto nego, speed and duplex) */
+    bcrvalue &= ~(LAN8742_BCR_AUTONEGO_EN | LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);
+    
+    if(LinkState == LAN8742_STATUS_100MBITS_FULLDUPLEX)
+    {
+      bcrvalue |= (LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);
+    }
+    else if (LinkState == LAN8742_STATUS_100MBITS_HALFDUPLEX)
+    {
+      bcrvalue |= LAN8742_BCR_SPEED_SELECT;
+    }
+    else if (LinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX)
+    {
+      bcrvalue |= LAN8742_BCR_DUPLEX_MODE;
+    }
+    else
+    {
+      /* Wrong link status parameter */
+      status = LAN8742_STATUS_ERROR;
+    }	
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+  
+  if(status == LAN8742_STATUS_OK)
+  {
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, bcrvalue) < 0)
+    {
+      status = LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  
+  return status;
+}
+
+/**
+  * @brief  Enable loopback mode.
+  * @param  pObj: Pointer to device object. 
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval |= LAN8742_BCR_LOOPBACK;
+    
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status = LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+  
+  return status;
+}
+
+/**
+  * @brief  Disable loopback mode.
+  * @param  pObj: Pointer to device object. 
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval &= ~LAN8742_BCR_LOOPBACK;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Enable IT source.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT source to be enabled
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0)
+  {
+    readval |= Interrupt;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Disable IT source.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT source to be disabled
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0)
+  {
+    readval &= ~Interrupt;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0)
+    {
+      status = LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Clear IT flag.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT flag to be cleared
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  */
+int32_t  LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;  
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) < 0)
+  {
+    status =  LAN8742_STATUS_READ_ERROR;
+  }
+  
+  return status;
+}
+
+/**
+  * @brief  Get IT Flag status.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT Flag to be checked, 
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT  
+  * @retval 1 IT flag is SET
+  *         0 IT flag is RESET
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  */
+int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = 0;
+
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) >= 0)
+  {
+    status = ((readval & Interrupt) == Interrupt);
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+	
+  return status;
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */      
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/lwip/ports/drivers/stm32h7/lan8742.h b/lwip/ports/drivers/stm32h7/lan8742.h
new file mode 100644
index 0000000..c1620dd
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/lan8742.h
@@ -0,0 +1,448 @@
+/**
+  ******************************************************************************
+  * @file    lan8742.h
+  * @author  MCD Application Team
+  * @brief   This file contains all the functions prototypes for the
+  *          lan8742.c PHY driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef LAN8742_H
+#define LAN8742_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif   
+   
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Component
+  * @{
+  */
+    
+/** @defgroup LAN8742
+  * @{
+  */    
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup LAN8742_Exported_Constants LAN8742 Exported Constants
+  * @{
+  */ 
+  
+/** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping
+  * @{
+  */ 
+#define LAN8742_BCR      ((uint16_t)0x0000U)
+#define LAN8742_BSR      ((uint16_t)0x0001U)
+#define LAN8742_PHYI1R   ((uint16_t)0x0002U)
+#define LAN8742_PHYI2R   ((uint16_t)0x0003U)
+#define LAN8742_ANAR     ((uint16_t)0x0004U)
+#define LAN8742_ANLPAR   ((uint16_t)0x0005U)
+#define LAN8742_ANER     ((uint16_t)0x0006U)
+#define LAN8742_ANNPTR   ((uint16_t)0x0007U)
+#define LAN8742_ANNPRR   ((uint16_t)0x0008U)
+#define LAN8742_MMDACR   ((uint16_t)0x000DU)
+#define LAN8742_MMDAADR  ((uint16_t)0x000EU)
+#define LAN8742_ENCTR    ((uint16_t)0x0010U)
+#define LAN8742_MCSR     ((uint16_t)0x0011U)
+#define LAN8742_SMR      ((uint16_t)0x0012U)
+#define LAN8742_TPDCR    ((uint16_t)0x0018U)
+#define LAN8742_TCSR     ((uint16_t)0x0019U)
+#define LAN8742_SECR     ((uint16_t)0x001AU)
+#define LAN8742_SCSIR    ((uint16_t)0x001BU)
+#define LAN8742_CLR      ((uint16_t)0x001CU)
+#define LAN8742_ISFR     ((uint16_t)0x001DU)
+#define LAN8742_IMR      ((uint16_t)0x001EU)
+#define LAN8742_PHYSCSR  ((uint16_t)0x001FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_BCR_Bit_Definition LAN8742 BCR Bit Definition
+  * @{
+  */    
+#define LAN8742_BCR_SOFT_RESET         ((uint16_t)0x8000U)
+#define LAN8742_BCR_LOOPBACK           ((uint16_t)0x4000U)
+#define LAN8742_BCR_SPEED_SELECT       ((uint16_t)0x2000U)
+#define LAN8742_BCR_AUTONEGO_EN        ((uint16_t)0x1000U)
+#define LAN8742_BCR_POWER_DOWN         ((uint16_t)0x0800U)
+#define LAN8742_BCR_ISOLATE            ((uint16_t)0x0400U)
+#define LAN8742_BCR_RESTART_AUTONEGO   ((uint16_t)0x0200U)
+#define LAN8742_BCR_DUPLEX_MODE        ((uint16_t)0x0100U) 
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_BSR_Bit_Definition LAN8742 BSR Bit Definition
+  * @{
+  */   
+#define LAN8742_BSR_100BASE_T4       ((uint16_t)0x8000U)
+#define LAN8742_BSR_100BASE_TX_FD    ((uint16_t)0x4000U)
+#define LAN8742_BSR_100BASE_TX_HD    ((uint16_t)0x2000U)
+#define LAN8742_BSR_10BASE_T_FD      ((uint16_t)0x1000U)
+#define LAN8742_BSR_10BASE_T_HD      ((uint16_t)0x0800U)
+#define LAN8742_BSR_100BASE_T2_FD    ((uint16_t)0x0400U)
+#define LAN8742_BSR_100BASE_T2_HD    ((uint16_t)0x0200U)
+#define LAN8742_BSR_EXTENDED_STATUS  ((uint16_t)0x0100U)
+#define LAN8742_BSR_AUTONEGO_CPLT    ((uint16_t)0x0020U)
+#define LAN8742_BSR_REMOTE_FAULT     ((uint16_t)0x0010U)
+#define LAN8742_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
+#define LAN8742_BSR_LINK_STATUS      ((uint16_t)0x0004U)
+#define LAN8742_BSR_JABBER_DETECT    ((uint16_t)0x0002U)
+#define LAN8742_BSR_EXTENDED_CAP     ((uint16_t)0x0001U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_PHYI1R_Bit_Definition LAN8742 PHYI1R Bit Definition
+  * @{
+  */
+#define LAN8742_PHYI1R_OUI_3_18           ((uint16_t)0xFFFFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_PHYI2R_Bit_Definition LAN8742 PHYI2R Bit Definition
+  * @{
+  */
+#define LAN8742_PHYI2R_OUI_19_24          ((uint16_t)0xFC00U)
+#define LAN8742_PHYI2R_MODEL_NBR          ((uint16_t)0x03F0U)
+#define LAN8742_PHYI2R_REVISION_NBR       ((uint16_t)0x000FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANAR_Bit_Definition LAN8742 ANAR Bit Definition
+  * @{
+  */
+#define LAN8742_ANAR_NEXT_PAGE               ((uint16_t)0x8000U)
+#define LAN8742_ANAR_REMOTE_FAULT            ((uint16_t)0x2000U)
+#define LAN8742_ANAR_PAUSE_OPERATION         ((uint16_t)0x0C00U)
+#define LAN8742_ANAR_PO_NOPAUSE              ((uint16_t)0x0000U)
+#define LAN8742_ANAR_PO_SYMMETRIC_PAUSE      ((uint16_t)0x0400U)
+#define LAN8742_ANAR_PO_ASYMMETRIC_PAUSE     ((uint16_t)0x0800U)
+#define LAN8742_ANAR_PO_ADVERTISE_SUPPORT    ((uint16_t)0x0C00U)
+#define LAN8742_ANAR_100BASE_TX_FD           ((uint16_t)0x0100U)
+#define LAN8742_ANAR_100BASE_TX              ((uint16_t)0x0080U)
+#define LAN8742_ANAR_10BASE_T_FD             ((uint16_t)0x0040U)
+#define LAN8742_ANAR_10BASE_T                ((uint16_t)0x0020U)
+#define LAN8742_ANAR_SELECTOR_FIELD          ((uint16_t)0x000FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANLPAR_Bit_Definition LAN8742 ANLPAR Bit Definition
+  * @{
+  */
+#define LAN8742_ANLPAR_NEXT_PAGE            ((uint16_t)0x8000U)
+#define LAN8742_ANLPAR_REMOTE_FAULT         ((uint16_t)0x2000U)
+#define LAN8742_ANLPAR_PAUSE_OPERATION      ((uint16_t)0x0C00U)
+#define LAN8742_ANLPAR_PO_NOPAUSE           ((uint16_t)0x0000U)
+#define LAN8742_ANLPAR_PO_SYMMETRIC_PAUSE   ((uint16_t)0x0400U)
+#define LAN8742_ANLPAR_PO_ASYMMETRIC_PAUSE  ((uint16_t)0x0800U)
+#define LAN8742_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
+#define LAN8742_ANLPAR_100BASE_TX_FD        ((uint16_t)0x0100U)
+#define LAN8742_ANLPAR_100BASE_TX           ((uint16_t)0x0080U)
+#define LAN8742_ANLPAR_10BASE_T_FD          ((uint16_t)0x0040U)
+#define LAN8742_ANLPAR_10BASE_T             ((uint16_t)0x0020U)
+#define LAN8742_ANLPAR_SELECTOR_FIELD       ((uint16_t)0x000FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANER_Bit_Definition LAN8742 ANER Bit Definition
+  * @{
+  */
+#define LAN8742_ANER_RX_NP_LOCATION_ABLE    ((uint16_t)0x0040U)
+#define LAN8742_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
+#define LAN8742_ANER_PARALLEL_DETECT_FAULT  ((uint16_t)0x0010U)
+#define LAN8742_ANER_LP_NP_ABLE             ((uint16_t)0x0008U)
+#define LAN8742_ANER_NP_ABLE                ((uint16_t)0x0004U)
+#define LAN8742_ANER_PAGE_RECEIVED          ((uint16_t)0x0002U)
+#define LAN8742_ANER_LP_AUTONEG_ABLE        ((uint16_t)0x0001U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANNPTR_Bit_Definition LAN8742 ANNPTR Bit Definition
+  * @{
+  */
+#define LAN8742_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
+#define LAN8742_ANNPTR_MESSAGE_PAGE      ((uint16_t)0x2000U)
+#define LAN8742_ANNPTR_ACK2              ((uint16_t)0x1000U)
+#define LAN8742_ANNPTR_TOGGLE            ((uint16_t)0x0800U)
+#define LAN8742_ANNPTR_MESSAGGE_CODE     ((uint16_t)0x07FFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANNPRR_Bit_Definition LAN8742 ANNPRR Bit Definition
+  * @{
+  */
+#define LAN8742_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
+#define LAN8742_ANNPRR_ACK               ((uint16_t)0x4000U)
+#define LAN8742_ANNPRR_MESSAGE_PAGE      ((uint16_t)0x2000U)
+#define LAN8742_ANNPRR_ACK2              ((uint16_t)0x1000U)
+#define LAN8742_ANNPRR_TOGGLE            ((uint16_t)0x0800U)
+#define LAN8742_ANNPRR_MESSAGGE_CODE     ((uint16_t)0x07FFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_MMDACR_Bit_Definition LAN8742 MMDACR Bit Definition
+  * @{
+  */
+#define LAN8742_MMDACR_MMD_FUNCTION       ((uint16_t)0xC000U) 
+#define LAN8742_MMDACR_MMD_FUNCTION_ADDR  ((uint16_t)0x0000U)
+#define LAN8742_MMDACR_MMD_FUNCTION_DATA  ((uint16_t)0x4000U)
+#define LAN8742_MMDACR_MMD_DEV_ADDR       ((uint16_t)0x001FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ENCTR_Bit_Definition LAN8742 ENCTR Bit Definition
+  * @{
+  */
+#define LAN8742_ENCTR_TX_ENABLE             ((uint16_t)0x8000U)
+#define LAN8742_ENCTR_TX_TIMER              ((uint16_t)0x6000U)
+#define LAN8742_ENCTR_TX_TIMER_1S           ((uint16_t)0x0000U)
+#define LAN8742_ENCTR_TX_TIMER_768MS        ((uint16_t)0x2000U)
+#define LAN8742_ENCTR_TX_TIMER_512MS        ((uint16_t)0x4000U)
+#define LAN8742_ENCTR_TX_TIMER_265MS        ((uint16_t)0x6000U)
+#define LAN8742_ENCTR_RX_ENABLE             ((uint16_t)0x1000U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL       ((uint16_t)0x0C00U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_64MS  ((uint16_t)0x0000U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_1S    ((uint16_t)0x0C00U)
+#define LAN8742_ENCTR_EX_CROSS_OVER         ((uint16_t)0x0002U)
+#define LAN8742_ENCTR_EX_MANUAL_CROSS_OVER  ((uint16_t)0x0001U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_MCSR_Bit_Definition LAN8742 MCSR Bit Definition
+  * @{
+  */
+#define LAN8742_MCSR_EDPWRDOWN        ((uint16_t)0x2000U)
+#define LAN8742_MCSR_FARLOOPBACK      ((uint16_t)0x0200U)
+#define LAN8742_MCSR_ALTINT           ((uint16_t)0x0040U)
+#define LAN8742_MCSR_ENERGYON         ((uint16_t)0x0002U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_SMR_Bit_Definition LAN8742 SMR Bit Definition
+  * @{
+  */
+#define LAN8742_SMR_MODE       ((uint16_t)0x00E0U)
+#define LAN8742_SMR_PHY_ADDR   ((uint16_t)0x001FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_TPDCR_Bit_Definition LAN8742 TPDCR Bit Definition
+  * @{
+  */
+#define LAN8742_TPDCR_DELAY_IN                 ((uint16_t)0x8000U)
+#define LAN8742_TPDCR_LINE_BREAK_COUNTER       ((uint16_t)0x7000U)
+#define LAN8742_TPDCR_PATTERN_HIGH             ((uint16_t)0x0FC0U)
+#define LAN8742_TPDCR_PATTERN_LOW              ((uint16_t)0x003FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_TCSR_Bit_Definition LAN8742 TCSR Bit Definition
+  * @{
+  */
+#define LAN8742_TCSR_TDR_ENABLE           ((uint16_t)0x8000U)
+#define LAN8742_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
+#define LAN8742_TCSR_TDR_CH_CABLE_TYPE    ((uint16_t)0x0600U)
+#define LAN8742_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
+#define LAN8742_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
+#define LAN8742_TCSR_TDR_CH_CABLE_OPEN    ((uint16_t)0x0400U)
+#define LAN8742_TCSR_TDR_CH_CABLE_MATCH   ((uint16_t)0x0600U)
+#define LAN8742_TCSR_TDR_CH_STATUS        ((uint16_t)0x0100U)
+#define LAN8742_TCSR_TDR_CH_LENGTH        ((uint16_t)0x00FFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_SCSIR_Bit_Definition LAN8742 SCSIR Bit Definition
+  * @{
+  */
+#define LAN8742_SCSIR_AUTO_MDIX_ENABLE    ((uint16_t)0x8000U)
+#define LAN8742_SCSIR_CHANNEL_SELECT      ((uint16_t)0x2000U)
+#define LAN8742_SCSIR_SQE_DISABLE         ((uint16_t)0x0800U)
+#define LAN8742_SCSIR_XPOLALITY           ((uint16_t)0x0010U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_CLR_Bit_Definition LAN8742 CLR Bit Definition
+  * @{
+  */
+#define LAN8742_CLR_CABLE_LENGTH       ((uint16_t)0xF000U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_IMR_ISFR_Bit_Definition LAN8742 IMR ISFR Bit Definition
+  * @{
+  */
+#define LAN8742_INT_8       ((uint16_t)0x0100U)
+#define LAN8742_INT_7       ((uint16_t)0x0080U)
+#define LAN8742_INT_6       ((uint16_t)0x0040U)
+#define LAN8742_INT_5       ((uint16_t)0x0020U)
+#define LAN8742_INT_4       ((uint16_t)0x0010U)
+#define LAN8742_INT_3       ((uint16_t)0x0008U)
+#define LAN8742_INT_2       ((uint16_t)0x0004U)
+#define LAN8742_INT_1       ((uint16_t)0x0002U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_PHYSCSR_Bit_Definition LAN8742 PHYSCSR Bit Definition
+  * @{
+  */
+#define LAN8742_PHYSCSR_AUTONEGO_DONE   ((uint16_t)0x1000U)
+#define LAN8742_PHYSCSR_HCDSPEEDMASK    ((uint16_t)0x001CU)
+#define LAN8742_PHYSCSR_10BT_HD         ((uint16_t)0x0004U)
+#define LAN8742_PHYSCSR_10BT_FD         ((uint16_t)0x0014U)
+#define LAN8742_PHYSCSR_100BTX_HD       ((uint16_t)0x0008U)
+#define LAN8742_PHYSCSR_100BTX_FD       ((uint16_t)0x0018U) 
+/**
+  * @}
+  */
+    
+/** @defgroup LAN8742_Status LAN8742 Status
+  * @{
+  */    
+
+#define  LAN8742_STATUS_READ_ERROR            ((int32_t)-5)
+#define  LAN8742_STATUS_WRITE_ERROR           ((int32_t)-4)
+#define  LAN8742_STATUS_ADDRESS_ERROR         ((int32_t)-3)
+#define  LAN8742_STATUS_RESET_TIMEOUT         ((int32_t)-2)
+#define  LAN8742_STATUS_ERROR                 ((int32_t)-1)
+#define  LAN8742_STATUS_OK                    ((int32_t) 0)
+#define  LAN8742_STATUS_LINK_DOWN             ((int32_t) 1)
+#define  LAN8742_STATUS_100MBITS_FULLDUPLEX   ((int32_t) 2)
+#define  LAN8742_STATUS_100MBITS_HALFDUPLEX   ((int32_t) 3)
+#define  LAN8742_STATUS_10MBITS_FULLDUPLEX    ((int32_t) 4)
+#define  LAN8742_STATUS_10MBITS_HALFDUPLEX    ((int32_t) 5)
+#define  LAN8742_STATUS_AUTONEGO_NOTDONE      ((int32_t) 6)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_IT_Flags LAN8742 IT Flags
+  * @{
+  */     
+#define  LAN8742_WOL_IT                        LAN8742_INT_8
+#define  LAN8742_ENERGYON_IT                   LAN8742_INT_7
+#define  LAN8742_AUTONEGO_COMPLETE_IT          LAN8742_INT_6
+#define  LAN8742_REMOTE_FAULT_IT               LAN8742_INT_5
+#define  LAN8742_LINK_DOWN_IT                  LAN8742_INT_4
+#define  LAN8742_AUTONEGO_LP_ACK_IT            LAN8742_INT_3
+#define  LAN8742_PARALLEL_DETECTION_FAULT_IT   LAN8742_INT_2
+#define  LAN8742_AUTONEGO_PAGE_RECEIVED_IT     LAN8742_INT_1
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported types ------------------------------------------------------------*/ 
+/** @defgroup LAN8742_Exported_Types LAN8742 Exported Types
+  * @{
+  */
+typedef int32_t  (*lan8742_Init_Func) (void); 
+typedef int32_t  (*lan8742_DeInit_Func) (void);
+typedef int32_t  (*lan8742_ReadReg_Func)   (uint32_t, uint32_t, uint32_t *);
+typedef int32_t  (*lan8742_WriteReg_Func)  (uint32_t, uint32_t, uint32_t);
+typedef int32_t  (*lan8742_GetTick_Func)  (void);
+
+typedef struct 
+{                   
+  lan8742_Init_Func      Init; 
+  lan8742_DeInit_Func    DeInit;
+  lan8742_WriteReg_Func  WriteReg;
+  lan8742_ReadReg_Func   ReadReg; 
+  lan8742_GetTick_Func   GetTick;   
+} lan8742_IOCtx_t;  
+
+  
+typedef struct 
+{
+  uint32_t            DevAddr;
+  uint32_t            Is_Initialized;
+  lan8742_IOCtx_t     IO;
+  void               *pData;
+}lan8742_Object_t;
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup LAN8742_Exported_Functions LAN8742 Exported Functions
+  * @{
+  */
+int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx);
+int32_t LAN8742_Init(lan8742_Object_t *pObj);
+int32_t LAN8742_DeInit(lan8742_Object_t *pObj);
+int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj);
+int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj);
+int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj);
+int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj);
+int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState);
+int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj);
+int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj);
+int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
+int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
+int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt);
+int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt);
+/**
+  * @}
+  */ 
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LAN8742_H */
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */       
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/lwip/ports/drivers/stm32h7/port_conf.h b/lwip/ports/drivers/stm32h7/port_conf.h
new file mode 100644
index 0000000..06c130d
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/port_conf.h
@@ -0,0 +1,44 @@
+#ifndef RTEMS_LWIP_LWIP_PORTS_DRIVERS_STM32H7_RTEMS_CONF_H_
+#define RTEMS_LWIP_LWIP_PORTS_DRIVERS_STM32H7_RTEMS_CONF_H_
+
+#include "lwipopts.h"
+
+/* RTEMS priorities range from 1 (highest) to 255 (lowest) */
+#ifndef RTEMS_LWIP_INTERFACE_THREAD_PRIORITY
+#define RTEMS_LWIP_INTERFACE_THREAD_PRIORITY    ( 50 )
+#endif
+
+/* Stack size of the interface thread */
+#ifndef RTEMS_LWIP_INTERFACE_THREAD_STACK_SIZE
+#define RTEMS_LWIP_INTERFACE_THREAD_STACK_SIZE  ( RTEMS_MINIMUM_STACK_SIZE )
+#endif
+
+#ifndef RTEMS_LWIP_ETH_DMA_TRANSMIT_TIMEOUT
+#define RTEMS_LWIP_ETH_DMA_TRANSMIT_TIMEOUT     ( 20U )
+#endif
+
+/* The MPU protection is unreliable for the Socket API. The exact cause is not know yet.
+It's safer to always clean data cache for now */
+#ifndef RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU
+#define RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU     1
+#endif
+
+#ifndef RTEMS_LWIP_DHCP_PRINTOUT
+#define RTEMS_LWIP_DHCP_PRINTOUT                  1
+#endif
+
+#ifndef LWIP_RAM_HEAP_POINTER
+#define LWIP_RAM_HEAP_POINTER                     (0x30040000)
+#endif
+
+#ifndef MEM_SIZE
+#define MEM_SIZE                                  (8 * 1024)
+#endif
+
+#if NO_SYS == 1
+#ifndef RTEMS_LWIP_DHCP_TASK_INTERVAL_MS
+#define RTEMS_LWIP_DHCP_TASK_INTERVAL_MS 500
+#endif
+#endif /* NO_SYS == 1 */
+
+#endif /* RTEMS_LWIP_LWIP_PORTS_DRIVERS_STM32H7_RTEMS_CONF_H_ */
diff --git a/lwip/ports/drivers/stm32h7/template/lwipopts_template.h b/lwip/ports/drivers/stm32h7/template/lwipopts_template.h
new file mode 100644
index 0000000..b5f4b58
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/template/lwipopts_template.h
@@ -0,0 +1,292 @@
+/**
+  ******************************************************************************
+  * @file    LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/lwipopts.h
+  * @author  MCD Application Team
+  * @brief   lwIP Options Configuration.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
+  * All rights reserved.</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted, provided that the following conditions are met:
+  *
+  * 1. Redistribution 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 of STMicroelectronics nor the names of other
+  *    contributors to this software may be used to endorse or promote products
+  *    derived from this software without specific written permission.
+  * 4. This software, including modifications and/or derivative works of this
+  *    software, must execute solely and exclusively on microcontroller or
+  *    microprocessor devices manufactured by or for STMicroelectronics.
+  * 5. Redistribution and use of this software other than as permitted under
+  *    this license is void and will automatically terminate your rights under
+  *    this license.
+  *
+  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
+  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
+  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
+  * SHALL STMICROELECTRONICS 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.
+  *
+  ******************************************************************************
+  */
+
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+#ifdef __rtems__
+#include "bsp.h"
+#endif
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT        0
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS                      1
+
+#define LWIP_NETIF_API              0
+
+/* ---------- Memory options ---------- */
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+   byte alignment -> define MEM_ALIGNMENT to 2. */
+#define MEM_ALIGNMENT               4
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#define MEM_SIZE                    (8*1024)
+
+/* Relocate the LwIP RAM heap pointer. Place in SRAM3 */
+#define LWIP_RAM_HEAP_POINTER       (0x30040000)
+
+/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
+   sends a lot of data out of ROM (or other static memory), this
+   should be set high. */
+#define MEMP_NUM_PBUF               10
+/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+   per active UDP "connection". */
+#define MEMP_NUM_UDP_PCB            6
+/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
+   connections. */
+#define MEMP_NUM_TCP_PCB            10
+/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
+   connections. */
+#define MEMP_NUM_TCP_PCB_LISTEN     5
+/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
+   segments. */
+#define MEMP_NUM_TCP_SEG            8
+/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
+   timeouts. */
+#define MEMP_NUM_SYS_TIMEOUT        10
+
+
+/* ---------- Pbuf options ---------- */
+/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
+   @ note: used to allocate Tx pbufs only */
+#define PBUF_POOL_SIZE              4
+
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#define PBUF_POOL_BUFSIZE           1528
+
+/* LWIP_SUPPORT_CUSTOM_PBUF == 1: to pass directly MAC Rx buffers to the stack
+   no copy is needed */
+#define LWIP_SUPPORT_CUSTOM_PBUF    1
+
+/* ---------- IPv4 options ---------- */
+#define LWIP_IPV4                   1
+
+/* ---------- TCP options ---------- */
+#define LWIP_TCP                    1
+#define TCP_TTL                     255
+
+/* Controls if TCP should queue segments that arrive out of
+   order. Define to 0 if your device is low on memory. */
+#define TCP_QUEUE_OOSEQ             0
+
+/* TCP Maximum segment size. */
+#define TCP_MSS                     (1500 - 40)   /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
+
+/* TCP sender buffer space (bytes). */
+#define TCP_SND_BUF                 (4*TCP_MSS)
+
+/*  TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
+  as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
+
+#define TCP_SND_QUEUELEN            (2* TCP_SND_BUF/TCP_MSS)
+
+/* TCP receive window. */
+#define TCP_WND                     (2*TCP_MSS)
+
+/* ---------- ICMP options ---------- */
+#define LWIP_ICMP                   1
+
+/* ---------- DHCP options ---------- */
+#define LWIP_DHCP                   1
+
+/* ---------- UDP options ---------- */
+#define LWIP_UDP                    1
+#define UDP_TTL                     255
+
+/* ---------- link callback options ---------- */
+/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
+ * whenever the link changes (i.e., link down)
+ */
+#define LWIP_NETIF_LINK_CALLBACK    1
+
+
+/* Static IP ADDRESS */
+#define IP_ADDR0   169
+#define IP_ADDR1   254
+#define IP_ADDR2   1
+#define IP_ADDR3   38
+
+/* NETMASK */
+#define NETMASK_ADDR0   255
+#define NETMASK_ADDR1   255
+#define NETMASK_ADDR2   0
+#define NETMASK_ADDR3   0
+
+/* Gateway Address */
+#define GW_ADDR0   192
+#define GW_ADDR1   168
+#define GW_ADDR2   178
+#define GW_ADDR3   1
+
+
+/*
+   --------------------------------------
+   ---------- Checksum options ----------
+   --------------------------------------
+*/
+
+/*
+The STM32H7xx allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
+ - To use this feature let the following define uncommented.
+ - To disable it and process by CPU comment the  the checksum.
+*/
+#define CHECKSUM_BY_HARDWARE
+
+
+#ifdef CHECKSUM_BY_HARDWARE
+  /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
+  #define CHECKSUM_GEN_IP                 0
+  /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
+  #define CHECKSUM_GEN_UDP                0
+  /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
+  #define CHECKSUM_GEN_TCP                0
+  /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
+  #define CHECKSUM_CHECK_IP               0
+  /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
+  #define CHECKSUM_CHECK_UDP              0
+  /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
+  #define CHECKSUM_CHECK_TCP              0
+  /* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
+  #define CHECKSUM_GEN_ICMP               0
+#else
+  /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
+  #define CHECKSUM_GEN_IP                 1
+  /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
+  #define CHECKSUM_GEN_UDP                1
+  /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
+  #define CHECKSUM_GEN_TCP                1
+  /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
+  #define CHECKSUM_CHECK_IP               1
+  /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
+  #define CHECKSUM_CHECK_UDP              1
+  /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
+  #define CHECKSUM_CHECK_TCP              1
+  /* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/
+  #define CHECKSUM_GEN_ICMP               1
+#endif
+
+
+/*
+   ----------------------------------------------
+   ---------- Sequential layer options ----------
+   ----------------------------------------------
+*/
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN                    0
+
+/*
+   ------------------------------------
+   ---------- Socket options ----------
+   ------------------------------------
+*/
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET                     0
+
+/*
+   ------------------------------------
+   ---------- httpd options ----------
+   ------------------------------------
+*/
+/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the
+ * file system (to prevent changing the file included in CVS) */
+#define HTTPD_USE_CUSTOM_FSDATA   1
+
+
+/*
+   ---------------------------------
+   ---------- OS options ----------
+   ---------------------------------
+*/
+
+#ifdef __rtems__
+#define TCPIP_THREAD_NAME              "LWIP"
+#define TCPIP_THREAD_STACKSIZE          RTEMS_MINIMUM_STACK_SIZE
+#define TCPIP_MBOX_SIZE                 6
+#define DEFAULT_UDP_RECVMBOX_SIZE       6
+#define DEFAULT_TCP_RECVMBOX_SIZE       6
+#define DEFAULT_ACCEPTMBOX_SIZE         6
+#define DEFAULT_THREAD_STACKSIZE        500
+#define TCPIP_THREAD_PRIO               60
+#endif /* __rtems__ */
+
+/*
+   ---------------------------------
+   ---------- ASSERT options ----------
+   ---------------------------------
+*/
+#define LWIP_NOASSERT
+
+
+#define ETH_MAC_ADDR0    ((uint8_t)0x02)
+#define ETH_MAC_ADDR1    ((uint8_t)0x00)
+#define ETH_MAC_ADDR2    ((uint8_t)0x00)
+#define ETH_MAC_ADDR3    ((uint8_t)0x00)
+#define ETH_MAC_ADDR4    ((uint8_t)0x00)
+#define ETH_MAC_ADDR5    ((uint8_t)0x00)
+#define ETH_MAC_ADDR     { ETH_MAC_ADDR0, ETH_MAC_ADDR1, \
+                           ETH_MAC_ADDR2, ETH_MAC_ADDR3, \
+                           ETH_MAC_ADDR4, ETH_MAC_ADDR5 }
+
+/* #undef LWIP_DEBUG */
+
+#endif /* __LWIPOPTS_H__ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/lwip/ports/drivers/tms570_netif.h b/lwip/ports/drivers/tms570/include/rtems_lwip/tms570_netif.h
similarity index 74%
rename from lwip/ports/drivers/tms570_netif.h
rename to lwip/ports/drivers/tms570/include/rtems_lwip/tms570_netif.h
index 325249a..6636f3f 100644
--- a/lwip/ports/drivers/tms570_netif.h
+++ b/lwip/ports/drivers/tms570/include/rtems_lwip/tms570_netif.h
@@ -36,6 +36,37 @@
 
 //#define TMS570_NETIF_DEBUG 1
 
+/**
+ * While scanning phy addresses no alive phy was found.
+ * Return value of rpp_eth_hw_init() function.
+ */
+#define NO_PHY_ALIVE             -1
+/**
+ * Scanning default phy address, it was found it's not alive.
+ * Return value of rpp_eth_hw_init() function.
+ */
+#define DFLT_PHY_NOT_ALIVE       -1
+/**
+ * When setting autonegotiation parameters to EMAC module, there was found impossible mode (usually on timeout of autonegotiation).
+ * Return value of rpp_eth_hw_init_postInit() function.
+ */
+#define UNKN_DUPLEX_MODE         -2 /* this could mean that autonegotiation was not completed yet */
+/**
+ * Phy is down error.
+ * Return value of rpp_eth_init_postInit() function.
+ */
+#define PHY_LINK_DOWN            -3
+
+/**
+ * Memory requirements couldn't be satisfied.
+ */
+#define DHCP_MEM_ERR             -11
+
+/**
+ * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
+ */
+#define MAC_BIG_LETTERS           1
+
 #ifdef TMS570_NETIF_DEBUG
 #define tms570_eth_debug_printf sys_arch_printk
 #else
diff --git a/lwip/ports/drivers/phy_dp83848h.c b/lwip/ports/drivers/tms570/phy_dp83848h.c
similarity index 100%
rename from lwip/ports/drivers/phy_dp83848h.c
rename to lwip/ports/drivers/tms570/phy_dp83848h.c
diff --git a/lwip/ports/drivers/phy_dp83848h.h b/lwip/ports/drivers/tms570/phy_dp83848h.h
similarity index 100%
rename from lwip/ports/drivers/phy_dp83848h.h
rename to lwip/ports/drivers/tms570/phy_dp83848h.h
diff --git a/lwip/ports/drivers/tms570/template/lwipopts_template.h b/lwip/ports/drivers/tms570/template/lwipopts_template.h
new file mode 100644
index 0000000..fb55e7a
--- /dev/null
+++ b/lwip/ports/drivers/tms570/template/lwipopts_template.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved. 
+ * 
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ * 
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef LWIP_HDR_LWIPOPTS_H__
+#define LWIP_HDR_LWIPOPTS_H__
+
+/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
+#define NO_SYS                          0
+#define LWIP_NETCONN                    1
+#define LWIP_SOCKET                     1
+#define LWIP_DNS                        1
+
+#define LWIP_IPV6                       1
+#define LWIP_IPV4                       1
+
+#define LWIP_ETHERNET                   1
+#define LWIP_NETIF_API                  1
+/* Enable DHCP to test it, disable UDP checksum to easier inject packets */
+#define LWIP_DHCP                       1
+#define LWIP_TIMEVAL_PRIVATE            0
+#define LWIP_POSIX_SOCKETS_IO_NAMES     0
+
+/* Minimal changes to opt.h required for tcp unit tests: */
+#define MEM_SIZE                        16000
+#define TCP_SND_QUEUELEN                40
+#define MEMP_NUM_TCP_SEG                TCP_SND_QUEUELEN
+#define TCP_SND_BUF                     (12 * TCP_MSS)
+#define TCP_WND                         (10 * TCP_MSS)
+#define LWIP_WND_SCALE                  1
+#define TCP_RCV_SCALE                   0
+#define PBUF_POOL_SIZE                  400 // pbuf tests need ~200KByte
+
+/* Minimal changes to opt.h required for etharp unit tests: */
+#define ETHARP_SUPPORT_STATIC_ENTRIES   1
+
+#define ETH_IP_ADDR               0xC0A8F701 /* 192.168.247.1   */
+#define ETH_NETMASK               0xFFFFFF00 /* 255.255.255.0   */
+#define ETH_GW                    0xC0A8F7FE /* 192.168.247.254 */
+
+#define LWIP_NETIF_LINK_CALLBACK        1
+
+void tms570_eth_memp_avaible(int type);
+
+/*called from memp_free() when a memp pool was empty and an item is now available*/
+#define LWIP_HOOK_MEMP_AVAILABLE tms570_eth_memp_avaible
+
+#endif /* LWIP_HDR_LWIPOPTS_H__ */
diff --git a/lwip/ports/drivers/ti_drv_emac.h b/lwip/ports/drivers/tms570/ti_drv_emac.h
similarity index 100%
rename from lwip/ports/drivers/ti_drv_emac.h
rename to lwip/ports/drivers/tms570/ti_drv_emac.h
diff --git a/lwip/ports/drivers/ti_drv_mdio.h b/lwip/ports/drivers/tms570/ti_drv_mdio.h
similarity index 100%
rename from lwip/ports/drivers/ti_drv_mdio.h
rename to lwip/ports/drivers/tms570/ti_drv_mdio.h
diff --git a/lwip/ports/drivers/tms570_emac.h b/lwip/ports/drivers/tms570/tms570_emac.h
similarity index 100%
rename from lwip/ports/drivers/tms570_emac.h
rename to lwip/ports/drivers/tms570/tms570_emac.h
diff --git a/lwip/ports/drivers/tms570_netif.c b/lwip/ports/drivers/tms570/tms570_netif.c
similarity index 99%
rename from lwip/ports/drivers/tms570_netif.c
rename to lwip/ports/drivers/tms570/tms570_netif.c
index 8d14687..2c99362 100644
--- a/lwip/ports/drivers/tms570_netif.c
+++ b/lwip/ports/drivers/tms570/tms570_netif.c
@@ -54,13 +54,15 @@
 #include <bsp/tms570.h>
 #include <bsp/tms570-pinmux.h>
 #include "arch/cc.h"
-#include "eth_lwip.h"
+#include "rtems_lwip.h"
 #include "tms570_netif.h"
 #include "ti_drv_emac.h"
 #include "ti_drv_mdio.h"
 #include "phy_dp83848h.h"
 #include "tms570_emac.h"
 
+netif_init_fn eth_lwip_init_fnc = &tms570_eth_init_netif;
+
 #define LINK_SPEED_OF_YOUR_NETIF_IN_BPS 10000000
 
 /* Number of EMAC Instances */
@@ -150,6 +152,7 @@ static err_t tms570_eth_init_control_structures(struct netif *netif);
 static void tms570_eth_init_netif_fill(struct netif *netif);
 static void tms570_eth_init_buffer_descriptors(struct tms570_netif_state *nf_state);
 static void tms570_eth_init_set_pinmux();
+static void sys_arch_data_sync_barier();
 
 /***** initializing functions **********************************************/
 
@@ -1122,10 +1125,12 @@ tms570_eth_memp_avaible(int type)
     return;
   if (type != MEMP_PBUF_POOL)
     return;
-  netifapi_netif_common(eth_lwip_get_netif(0), tms570_eth_rx_pbuf_refill_single, NULL);
+  netifapi_netif_common(rtems_lwip_get_netif(0), tms570_eth_rx_pbuf_refill_single, NULL);
 }
 
-
+void sys_arch_data_sync_barier() {
+    _ARM_Data_synchronization_barrier();
+}
 
 #if TMS570_NETIF_DEBUG
 
diff --git a/lwip/ports/os/rtems/arch/cc.h b/lwip/ports/os/rtems/arch/cc.h
index 84138ff..0e298c7 100644
--- a/lwip/ports/os/rtems/arch/cc.h
+++ b/lwip/ports/os/rtems/arch/cc.h
@@ -39,6 +39,9 @@
 #ifndef __CC_H__
 #define __CC_H__
 
+/* Use timeval provided by RTEMS be defining this to 0 */
+#define LWIP_TIMEVAL_PRIVATE 0
+
 #include <stdio.h>
 #include <rtems/malloc.h>  /*printk*/
 #include <inttypes.h>
diff --git a/lwip/ports/os/rtems/arch/sys_arch.c b/lwip/ports/os/rtems/arch/sys_arch.c
index ca7f8be..5fd8064 100644
--- a/lwip/ports/os/rtems/arch/sys_arch.c
+++ b/lwip/ports/os/rtems/arch/sys_arch.c
@@ -37,15 +37,21 @@
  * DETAILS: ./lwip/doc/sys_arch.txt
  */
 
+/* lwIP includes. */
+#include "lwip/debug.h"
+#include "lwip/def.h"
+#include "lwip/sys.h"
+#include "lwip/mem.h"
+#include "lwip/stats.h"
+
+#if !NO_SYS
+
+#include "sys_arch.h"
 #include <stdint.h>
 #include <arch/cc.h>
 #include <rtems/rtems/clock.h>
 #include <rtems/rtems/sem.h>
 #include <rtems.h>
-#include "sys_arch.h"
-#include "lwip/err.h"
-#include "lwip/tcpip.h"
-#include "lwipopts.h"
 
 #define SYS_LWIP_MBOX_SIZE (sizeof(void *))
 
@@ -268,8 +274,21 @@ sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stack_s
   rtems_id id;
   rtems_status_code res;
 
+  rtems_name lwip_task_name = 0;
+  if(name == NULL) {
+    lwip_task_name = rtems_build_name('L', 'W', 'I', 'P');
+  }
+  else {
+    if(name[0] == '\0') {
+      lwip_task_name = rtems_build_name('L', 'W', 'I', 'P');
+    }
+    else {
+      lwip_task_name = rtems_build_name(name[0], name[1], name[2], name[3]);
+    }
+  }
+
   res = rtems_task_create(
-    rtems_build_name('L', 'W', 'I', 'P'),
+    lwip_task_name,
     prio,
     stack_size,
     RTEMS_PREEMPT,
@@ -376,3 +395,5 @@ sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
   return sys_mbox_trypost(q, msg);
 }
 
+#endif /* NO_SYS == 0 */
+
diff --git a/lwip/ports/os/rtems/arch/sys_arch.h b/lwip/ports/os/rtems/arch/sys_arch.h
index c89abd4..f4a73a7 100644
--- a/lwip/ports/os/rtems/arch/sys_arch.h
+++ b/lwip/ports/os/rtems/arch/sys_arch.h
@@ -39,17 +39,23 @@
 #ifndef __ARCH_SYS_ARCH_H__
 #define __ARCH_SYS_ARCH_H__
 
+#include "lwip/opt.h"
+
+#if (NO_SYS != 0)
+#error "RTEMS SYS_ARCH cannot be compiled in NO_SYS variant"
+#endif
+
 #include <rtems/rtems/sem.h>
 #include <rtems/rtems/intr.h>
 #include <rtems/score/cpu.h>
 #include <bsp/irq-generic.h>
-//#include "eth_lwip_default.h"
 
-/* Typedefs for the various port-specific types. */
-#if defined(NO_SYS) && NO_SYS
-  #error "RTEMS SYS_ARCH cannot be compiled in NO_SYS variant"
+#ifdef __cplusplus
+extern "C" {
 #endif
 
+/* Typedefs for the various port-specific types. */
+
 #define sys_arch_printk printk
 
 typedef struct {
@@ -105,4 +111,8 @@ sys_prot_t sys_arch_protect();
 
 void sys_arch_unprotect(sys_prot_t pval);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __ARCH_SYS_ARCH_H__ */
diff --git a/lwip/ports/os/rtems/defaults/lwipopts.h b/lwip/ports/os/rtems/defaults/lwipopts.h
new file mode 100644
index 0000000..12fe795
--- /dev/null
+++ b/lwip/ports/os/rtems/defaults/lwipopts.h
@@ -0,0 +1,37 @@
+#ifndef RTEMS_LWIP_LWIP_PORTS_OS_RTEMS_LWIPOPTS_H_
+#define RTEMS_LWIP_LWIP_PORTS_OS_RTEMS_LWIPOPTS_H_
+
+/**
+ * @brief   This is the default lwipopts.h file which will be used if none is supplied by the
+ *          user.
+ * @details
+ * This might not work on each port depending on which configuration options are used
+ * and required by the port
+ */
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS                          0
+
+/* DHCP will be enabled by default */
+#define LWIP_DHCP                       1
+
+/* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) */
+#define LWIP_NETCONN                    1
+
+/* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) */
+#define LWIP_SOCKET                     1
+
+/* OS specific options */
+#define TCPIP_THREAD_NAME              "LWIP"
+#define TCPIP_THREAD_STACKSIZE          RTEMS_MINIMUM_STACK_SIZE
+#define TCPIP_MBOX_SIZE                 6
+#define DEFAULT_UDP_RECVMBOX_SIZE       6
+#define DEFAULT_TCP_RECVMBOX_SIZE       6
+#define DEFAULT_ACCEPTMBOX_SIZE         6
+#define DEFAULT_THREAD_STACKSIZE        500
+#define TCPIP_THREAD_PRIO               60
+
+#endif /* RTEMS_LWIP_LWIP_PORTS_OS_RTEMS_LWIPOPTS_H_ */
diff --git a/lwip/src/api/api_lib.c b/lwip/src/api/api_lib.c
index e03b8b7..acf6736 100644
--- a/lwip/src/api/api_lib.c
+++ b/lwip/src/api/api_lib.c
@@ -201,16 +201,16 @@ netconn_prepare_delete(struct netconn *conn)
 
   API_MSG_VAR_ALLOC(msg);
   API_MSG_VAR_REF(msg).conn = conn;
+#if LWIP_TCP
 #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
   /* get the time we started, which is later compared to
      sys_now() + conn->send_timeout */
   API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
 #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
-#if LWIP_TCP
   API_MSG_VAR_REF(msg).msg.sd.polls_left =
     ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
-#endif /* LWIP_TCP */
 #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
+#endif /* LWIP_TCP */
   err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg));
   API_MSG_VAR_FREE(msg);
 
@@ -500,7 +500,7 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
 
   NETCONN_MBOX_WAITING_INC(conn);
   if (netconn_is_nonblocking(conn)) {
-    if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_ARCH_TIMEOUT) {
+    if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_MBOX_EMPTY) {
       API_MSG_VAR_FREE_ACCEPT(msg);
       NETCONN_MBOX_WAITING_DEC(conn);
       return ERR_WOULDBLOCK;
@@ -597,7 +597,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf, u8_t apiflags)
   NETCONN_MBOX_WAITING_INC(conn);
   if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) ||
       (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) {
-    if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_ARCH_TIMEOUT) {
+    if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_MBOX_EMPTY) {
       err_t err;
       NETCONN_MBOX_WAITING_DEC(conn);
       err = netconn_err(conn);
diff --git a/lwip/src/api/api_msg.c b/lwip/src/api/api_msg.c
index ce485d5..3f08e03 100644
--- a/lwip/src/api/api_msg.c
+++ b/lwip/src/api/api_msg.c
@@ -54,8 +54,6 @@
 #include "lwip/mld6.h"
 #include "lwip/priv/tcpip_priv.h"
 
-#include "arch/sys_arch.h"
-
 #include <string.h>
 
 /* netconns are polled once per second (e.g. continue write on memory error) */
@@ -718,6 +716,9 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
   conn->pending_err = ERR_OK;
   conn->type = t;
   conn->pcb.tcp = NULL;
+#if LWIP_NETCONN_FULLDUPLEX
+  conn->mbox_threads_waiting = 0;
+#endif
 
   /* If all sizes are the same, every compiler should optimize this switch to nothing */
   switch (NETCONNTYPE_GROUP(t)) {
diff --git a/lwip/src/api/netdb.c b/lwip/src/api/netdb.c
index dfc5203..8771425 100644
--- a/lwip/src/api/netdb.c
+++ b/lwip/src/api/netdb.c
@@ -411,44 +411,4 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
   return 0;
 }
 
-int
-getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node,
-    size_t nodelen, char *service, size_t servicelen, int flags)
-{
-    int af; 
-    const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa;
-
-    (void) salen;
-
-    af = sa->sa_family;
-    if (af != AF_INET) {
-        return EAI_FAMILY;
-    }   
-
-    if ((flags & NI_NAMEREQD) != 0) {
-        return EAI_NONAME;
-    }   
-
-    /* FIXME: This return just the address value. Try resolving instead. */
-    if (node != NULL && nodelen > 0) {
-        if (inet_ntop(af, &sa_in->sin_addr, node, nodelen) == NULL) {
-            return EAI_FAIL;
-        }
-    }   
-
-    if (service != NULL && servicelen > 0) {
-        in_port_t port = ntohs(sa_in->sin_port);
-        int rv; 
-
-        rv = snprintf(service, servicelen, "%u", port);
-        if (rv <= 0) {
-            return EAI_FAIL;
-        } else if ((unsigned)rv >= servicelen) {
-            return EAI_OVERFLOW;
-        }
-    }   
-
-    return 0;
-}
-
 #endif /* LWIP_DNS && LWIP_SOCKET */
diff --git a/lwip/src/api/sockets.c b/lwip/src/api/sockets.c
index a331206..7852635 100644
--- a/lwip/src/api/sockets.c
+++ b/lwip/src/api/sockets.c
@@ -54,7 +54,6 @@
 #include "lwip/netif.h"
 #include "lwip/priv/tcpip_priv.h"
 #include "lwip/mld6.h"
-#include "arch/sys_arch.h"
 #if LWIP_CHECKSUM_ON_COPY
 #include "lwip/inet_chksum.h"
 #endif
@@ -689,7 +688,6 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
     err = netconn_peer(newconn, &naddr, &port);
     if (err != ERR_OK) {
       LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
-      netconn_delete(newconn);
       free_socket(nsock, 1);
       sock_set_errno(sock, err_to_errno(err));
       done_socket(sock);
@@ -2074,7 +2072,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
         /* Call lwip_selscan again: there could have been events between
            the last scan (without us on the list) and putting us on the list! */
         nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
-        if (!nready) {
+        if (nready < 0) {
+          set_errno(EBADF);
+        } else if (!nready) {
           /* Still none ready, just wait to be woken */
           if (timeout == 0) {
             /* Wait forever */
@@ -2103,7 +2103,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
             (exceptset && FD_ISSET(i, exceptset))) {
           struct lwip_sock *sock;
           SYS_ARCH_PROTECT(lev);
-          sock = tryget_socket_unconn_locked(i);
+          sock = tryget_socket_unconn_nouse(i);
+          LWIP_ASSERT("socket gone at the end of select", sock != NULL);
           if (sock != NULL) {
             /* for now, handle select_waiting==0... */
             LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
@@ -2111,7 +2112,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
               sock->select_waiting--;
             }
             SYS_ARCH_UNPROTECT(lev);
-            done_socket(sock);
           } else {
             SYS_ARCH_UNPROTECT(lev);
             /* Not a valid socket */
@@ -2148,6 +2148,11 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
         /* See what's set now after waiting */
         nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
         LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
+        if (nready < 0) {
+          set_errno(EBADF);
+          lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
+          return -1;
+        }
       }
     }
   }
diff --git a/lwip/src/api/tcpip.c b/lwip/src/api/tcpip.c
index 743553a..a7e312a 100644
--- a/lwip/src/api/tcpip.c
+++ b/lwip/src/api/tcpip.c
@@ -217,7 +217,7 @@ tcpip_thread_poll_one(void)
   int ret = 0;
   struct tcpip_msg *msg;
 
-  if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_ARCH_TIMEOUT) {
+  if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_MBOX_EMPTY) {
     LOCK_TCPIP_CORE();
     if (msg != NULL) {
       tcpip_thread_handle_msg(msg);
diff --git a/lwip/src/core/altcp.c b/lwip/src/core/altcp.c
index d46d6cd..4abef7c 100644
--- a/lwip/src/core/altcp.c
+++ b/lwip/src/core/altcp.c
@@ -501,6 +501,24 @@ altcp_get_port(struct altcp_pcb *conn, int local)
   return 0;
 }
 
+#if LWIP_TCP_KEEPALIVE
+void
+altcp_keepalive_disable(struct altcp_pcb *conn)
+{
+  if (conn && conn->fns && conn->fns->keepalive_disable) {
+    conn->fns->keepalive_disable(conn);
+  }
+}
+
+void
+altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count)
+{
+  if (conn && conn->fns && conn->fns->keepalive_enable) {
+      conn->fns->keepalive_enable(conn, idle, intvl, count);
+  }
+}
+#endif
+
 #ifdef LWIP_DEBUG
 enum tcp_state
 altcp_dbg_get_tcp_state(struct altcp_pcb *conn)
@@ -666,6 +684,24 @@ altcp_default_get_port(struct altcp_pcb *conn, int local)
   return 0;
 }
 
+#if LWIP_TCP_KEEPALIVE
+void
+altcp_default_keepalive_disable(struct altcp_pcb *conn)
+{
+  if (conn && conn->inner_conn) {
+    altcp_keepalive_disable(conn->inner_conn);
+  }
+}
+
+void
+altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count)
+{
+  if (conn && conn->inner_conn) {
+      altcp_keepalive_enable(conn->inner_conn, idle, intvl, count);
+  }
+}
+#endif
+
 #ifdef LWIP_DEBUG
 enum tcp_state
 altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn)
diff --git a/lwip/src/core/altcp_tcp.c b/lwip/src/core/altcp_tcp.c
index b715f04..867d2b4 100644
--- a/lwip/src/core/altcp_tcp.c
+++ b/lwip/src/core/altcp_tcp.c
@@ -49,6 +49,7 @@
 #include "lwip/altcp_tcp.h"
 #include "lwip/priv/altcp_priv.h"
 #include "lwip/tcp.h"
+#include "lwip/priv/tcp_priv.h"
 #include "lwip/mem.h"
 
 #include <string.h>
@@ -446,6 +447,31 @@ altcp_tcp_setprio(struct altcp_pcb *conn, u8_t prio)
   }
 }
 
+#if LWIP_TCP_KEEPALIVE
+static void
+altcp_tcp_keepalive_disable(struct altcp_pcb *conn)
+{
+  if (conn && conn->state) {
+    struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+    ALTCP_TCP_ASSERT_CONN(conn);
+    ip_reset_option(pcb, SOF_KEEPALIVE);
+  }
+}
+
+static void
+altcp_tcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t cnt)
+{
+  if (conn && conn->state) {
+    struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+    ALTCP_TCP_ASSERT_CONN(conn);
+    ip_set_option(pcb, SOF_KEEPALIVE);
+    pcb->keep_idle = idle ? idle : TCP_KEEPIDLE_DEFAULT;
+    pcb->keep_intvl = intvl ? intvl : TCP_KEEPINTVL_DEFAULT;
+    pcb->keep_cnt = cnt ? cnt : TCP_KEEPCNT_DEFAULT;
+  }
+}
+#endif
+
 static void
 altcp_tcp_dealloc(struct altcp_pcb *conn)
 {
@@ -535,6 +561,10 @@ const struct altcp_functions altcp_tcp_functions = {
   altcp_tcp_get_tcp_addrinfo,
   altcp_tcp_get_ip,
   altcp_tcp_get_port
+#if LWIP_TCP_KEEPALIVE
+  , altcp_tcp_keepalive_disable
+  , altcp_tcp_keepalive_enable
+#endif
 #ifdef LWIP_DEBUG
   , altcp_tcp_dbg_get_tcp_state
 #endif
diff --git a/lwip/src/core/init.c b/lwip/src/core/init.c
index b3737a3..3620e1d 100644
--- a/lwip/src/core/init.c
+++ b/lwip/src/core/init.c
@@ -237,8 +237,9 @@ PACK_STRUCT_END
 #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
 #endif
 #endif /* LWIP_NETCONN && LWIP_TCP */
-#if LWIP_SOCKET
-#endif /* LWIP_SOCKET */
+#if LWIP_NETCONN_FULLDUPLEX && !LWIP_NETCONN_SEM_PER_THREAD
+#error "For LWIP_NETCONN_FULLDUPLEX to work, LWIP_NETCONN_SEM_PER_THREAD is required"
+#endif
 
 
 /* Compile-time checks for deprecated options.
diff --git a/lwip/src/core/ipv4/dhcp.c b/lwip/src/core/ipv4/dhcp.c
index 534574f..fcf3a3c 100644
--- a/lwip/src/core/ipv4/dhcp.c
+++ b/lwip/src/core/ipv4/dhcp.c
@@ -127,6 +127,11 @@
 #define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
 #endif
 
+#ifndef LWIP_DHCP_INPUT_ERROR
+#define LWIP_DHCP_INPUT_ERROR(message, expression, handler) do { if (!(expression)) { \
+  handler;} } while(0)
+#endif
+
 /** Option handling: options are parsed in dhcp_parse_reply
  * and saved in an array where other functions can load them from.
  * This might be moved into the struct dhcp (not necessarily since
@@ -1365,10 +1370,10 @@ dhcp_release_and_stop(struct netif *netif)
       /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
     }
-  }
 
-  /* remove IP address from interface (prevents routing from selecting this interface) */
-  netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
+    /* remove IP address from interface (prevents routing from selecting this interface) */
+    netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
+  }
 
 #if LWIP_DHCP_AUTOIP_COOP
   if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
@@ -1579,58 +1584,58 @@ again:
         /* will be increased below */
         break;
       case (DHCP_OPTION_SUBNET_MASK):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
         break;
       case (DHCP_OPTION_ROUTER):
         decode_len = 4; /* only copy the first given router */
-        LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_ROUTER;
         break;
 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
       case (DHCP_OPTION_DNS_SERVER):
         /* special case: there might be more than one server */
-        LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
         /* limit number of DNS servers */
         decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
-        LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
         break;
 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
       case (DHCP_OPTION_LEASE_TIME):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
         break;
 #if LWIP_DHCP_GET_NTP_SRV
       case (DHCP_OPTION_NTP):
         /* special case: there might be more than one server */
-        LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
         /* limit number of NTP servers */
         decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS);
-        LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_NTP_SERVER;
         break;
 #endif /* LWIP_DHCP_GET_NTP_SRV*/
       case (DHCP_OPTION_OVERLOAD):
-        LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;);
         /* decode overload only in options, not in file/sname: invalid packet */
-        LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_OVERLOAD;
         break;
       case (DHCP_OPTION_MESSAGE_TYPE):
-        LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
         break;
       case (DHCP_OPTION_SERVER_ID):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_SERVER_ID;
         break;
       case (DHCP_OPTION_T1):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_T1;
         break;
       case (DHCP_OPTION_T2):
-        LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
         decode_idx = DHCP_OPTION_IDX_T2;
         break;
       default:
@@ -1662,7 +1667,7 @@ decode_next:
           if (decode_len > 4) {
             /* decode more than one u32_t */
             u16_t next_val_offset;
-            LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
+            LWIP_DHCP_INPUT_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
             dhcp_got_option(dhcp, decode_idx);
             dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
             decode_len = (u8_t)(decode_len - 4);
@@ -1677,7 +1682,7 @@ decode_next:
           } else if (decode_len == 4) {
             value = lwip_ntohl(value);
           } else {
-            LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
+            LWIP_DHCP_INPUT_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
             value = ((u8_t *)&value)[0];
           }
           dhcp_got_option(dhcp, decode_idx);
@@ -1690,7 +1695,7 @@ decode_next:
       offset_max = (u16_t)(offset_max - q->len);
       if (offset < offset_max) {
         q = q->next;
-        LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
+        LWIP_DHCP_INPUT_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
         options = (u8_t *)q->payload;
       } else {
         /* We've run out of bytes, probably no end marker. Don't proceed. */
diff --git a/lwip/src/core/ipv4/icmp.c b/lwip/src/core/ipv4/icmp.c
index a462ccd..59b493a 100644
--- a/lwip/src/core/ipv4/icmp.c
+++ b/lwip/src/core/ipv4/icmp.c
@@ -62,7 +62,7 @@
 #define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
 #endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
 
-/* The amount of data from the original packet to return in a dest-unreachable */
+/* The maximum amount of data from the original packet to return in a dest-unreachable */
 #define ICMP_DEST_UNREACH_DATASIZE 8
 
 static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
@@ -345,20 +345,26 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
   struct icmp_echo_hdr *icmphdr;
   ip4_addr_t iphdr_src;
   struct netif *netif;
+  u16_t response_pkt_len;
 
   /* increase number of messages attempted to send */
   MIB2_STATS_INC(mib2.icmpoutmsgs);
 
-  /* ICMP header + IP header + 8 bytes of data */
-  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
-                 PBUF_RAM);
+  /* Keep IP header + up to 8 bytes */
+  response_pkt_len = IP_HLEN + ICMP_DEST_UNREACH_DATASIZE;
+  if (p->tot_len < response_pkt_len) {
+    response_pkt_len = p->tot_len;
+  }
+
+  /* ICMP header + part of original packet */
+  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + response_pkt_len, PBUF_RAM);
   if (q == NULL) {
     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
     MIB2_STATS_INC(mib2.icmpouterrors);
     return;
   }
   LWIP_ASSERT("check that first pbuf can hold icmp message",
-              (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
+              (q->len >= (sizeof(struct icmp_echo_hdr) + response_pkt_len)));
 
   iphdr = (struct ip_hdr *)p->payload;
   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
@@ -375,7 +381,7 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
 
   /* copy fields from original packet */
   SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
-          IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
+          response_pkt_len);
 
   ip4_addr_copy(iphdr_src, iphdr->src);
 #ifdef LWIP_HOOK_IP4_ROUTE_SRC
diff --git a/lwip/src/core/ipv6/dhcp6.c b/lwip/src/core/ipv6/dhcp6.c
index 7cf98a5..41444a4 100644
--- a/lwip/src/core/ipv6/dhcp6.c
+++ b/lwip/src/core/ipv6/dhcp6.c
@@ -451,7 +451,16 @@ dhcp6_msg_finalize(u16_t options_out_len, struct pbuf *p_out)
 static void
 dhcp6_information_request(struct netif *netif, struct dhcp6 *dhcp6)
 {
-  const u16_t requested_options[] = {DHCP6_OPTION_DNS_SERVERS, DHCP6_OPTION_DOMAIN_LIST, DHCP6_OPTION_SNTP_SERVERS};
+  const u16_t requested_options[] = {
+#if LWIP_DHCP6_PROVIDE_DNS_SERVERS
+    DHCP6_OPTION_DNS_SERVERS, 
+    DHCP6_OPTION_DOMAIN_LIST
+#endif
+#if LWIP_DHCP6_GET_NTP_SRV
+    , DHCP6_OPTION_SNTP_SERVERS
+#endif
+  };
+  
   u16_t msecs;
   struct pbuf *p_out;
   u16_t options_out_len;
@@ -527,7 +536,7 @@ dhcp6_handle_config_reply(struct netif *netif, struct pbuf *p_msg_in)
     u16_t idx;
     u8_t n;
 
-    memset(&dns_addr, 0, sizeof(dns_addr));
+    ip_addr_set_zero_ip6(&dns_addr);
     dns_addr6 = ip_2_ip6(&dns_addr);
     for (n = 0, idx = op_start; (idx < op_start + op_len) && (n < LWIP_DHCP6_PROVIDE_DNS_SERVERS);
          n++, idx += sizeof(struct ip6_addr_packed)) {
diff --git a/lwip/src/core/ipv6/icmp6.c b/lwip/src/core/ipv6/icmp6.c
index 167738a..4fd1021 100644
--- a/lwip/src/core/ipv6/icmp6.c
+++ b/lwip/src/core/ipv6/icmp6.c
@@ -57,9 +57,9 @@
 
 #include <string.h>
 
-#if LWIP_ICMP6_DATASIZE == 0
+#if !LWIP_ICMP6_DATASIZE || (LWIP_ICMP6_DATASIZE > (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN))
 #undef LWIP_ICMP6_DATASIZE
-#define LWIP_ICMP6_DATASIZE   8
+#define LWIP_ICMP6_DATASIZE   (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN)
 #endif
 
 /* Forward declarations */
@@ -387,26 +387,35 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data,
 {
   struct pbuf *q;
   struct icmp6_hdr *icmp6hdr;
+  u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE);
+  u16_t offset;
 
-  /* ICMPv6 header + IPv6 header + data */
-  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
+  /* ICMPv6 header + datalen (as much of the offending packet as possible) */
+  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen,
                  PBUF_RAM);
   if (q == NULL) {
     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
     ICMP6_STATS_INC(icmp6.memerr);
     return;
   }
-  LWIP_ASSERT("check that first pbuf can hold icmp 6message",
-             (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
+  LWIP_ASSERT("check that first pbuf can hold icmp6 header",
+             (q->len >= (sizeof(struct icmp6_hdr))));
 
   icmp6hdr = (struct icmp6_hdr *)q->payload;
   icmp6hdr->type = type;
   icmp6hdr->code = code;
   icmp6hdr->data = lwip_htonl(data);
 
-  /* copy fields from original packet */
-  SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
-          IP6_HLEN + LWIP_ICMP6_DATASIZE);
+  /* copy fields from original packet (which may be a chain of pbufs) */
+  offset = sizeof(struct icmp6_hdr);
+  while (p && datalen) {
+    u16_t len = LWIP_MIN(datalen, p->len);
+    err_t res = pbuf_take_at(q, p->payload, len, offset);
+    if (res != ERR_OK) break;
+    datalen -= len;
+    offset += len;
+    p = p->next;
+  }
 
   /* calculate checksum */
   icmp6hdr->chksum = 0;
diff --git a/lwip/src/core/ipv6/mld6.c b/lwip/src/core/ipv6/mld6.c
index 6387d46..a9c917d 100644
--- a/lwip/src/core/ipv6/mld6.c
+++ b/lwip/src/core/ipv6/mld6.c
@@ -253,7 +253,7 @@ mld6_input(struct pbuf *p, struct netif *inp)
       while (group != NULL) {
         if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
             (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
-          mld6_delayed_report(group, mld_hdr->max_resp_delay);
+          mld6_delayed_report(group, lwip_ntohs(mld_hdr->max_resp_delay));
         }
         group = group->next;
       }
@@ -265,7 +265,7 @@ mld6_input(struct pbuf *p, struct netif *inp)
       group = mld6_lookfor_group(inp, ip6_current_dest_addr());
       if (group != NULL) {
         /* Schedule a report. */
-        mld6_delayed_report(group, mld_hdr->max_resp_delay);
+        mld6_delayed_report(group, lwip_ntohs(mld_hdr->max_resp_delay));
       }
     }
     break; /* ICMP6_TYPE_MLQ */
diff --git a/lwip/src/core/ipv6/nd6.c b/lwip/src/core/ipv6/nd6.c
index db0c132..81992fa 100644
--- a/lwip/src/core/ipv6/nd6.c
+++ b/lwip/src/core/ipv6/nd6.c
@@ -693,11 +693,11 @@ nd6_input(struct pbuf *p, struct netif *inp)
         }
         mtu_opt = (struct mtu_option *)buffer;
         mtu32 = lwip_htonl(mtu_opt->mtu);
-        if ((mtu32 >= 1280) && (mtu32 <= 0xffff)) {
+        if ((mtu32 >= IP6_MIN_MTU_LENGTH) && (mtu32 <= 0xffff)) {
 #if LWIP_ND6_ALLOW_RA_UPDATES
           if (inp->mtu) {
             /* don't set the mtu for IPv6 higher than the netif driver supports */
-            inp->mtu6 = LWIP_MIN(inp->mtu, (u16_t)mtu32);
+            inp->mtu6 = LWIP_MIN(LWIP_MIN(inp->mtu, inp->mtu6), (u16_t)mtu32);
           } else {
             inp->mtu6 = (u16_t)mtu32;
           }
@@ -766,7 +766,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
 
         rdnss_opt = (struct rdnss_option *)buffer;
         num = (rdnss_opt->length - 1) / 2;
-        for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) {
+        for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++, copy_offset += sizeof(ip6_addr_p_t)) {
           ip_addr_t rdnss_address;
 
           /* Copy directly from pbuf to get an aligned, zoned copy of the prefix. */
@@ -1182,15 +1182,27 @@ nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
 {
   struct ns_header *ns_hdr;
   struct pbuf *p;
-  const ip6_addr_t *src_addr;
+  const ip6_addr_t *src_addr = NULL;
   u16_t lladdr_opt_len;
 
   LWIP_ASSERT("target address is required", target_addr != NULL);
 
-  if (!(flags & ND6_SEND_FLAG_ANY_SRC) &&
-      ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) {
-    /* Use link-local address as source address. */
-    src_addr = netif_ip6_addr(netif, 0);
+  if (!(flags & ND6_SEND_FLAG_ANY_SRC)) {
+    int i;
+    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
+      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
+            ip6_addr_netcmp(target_addr, netif_ip6_addr(netif, i))) {
+        src_addr = netif_ip6_addr(netif, i);
+        break;
+      }
+    }
+
+    if (i == LWIP_IPV6_NUM_ADDRESSES) {
+      LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NS: no available src address\n"));
+      ND6_STATS_INC(nd6.err);
+      return;
+    }
+
     /* calculate option length (in 8-byte-blocks) */
     lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3;
   } else {
@@ -2300,7 +2312,7 @@ nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif)
     return netif_mtu6(netif);
   }
 
-  return 1280; /* Minimum MTU */
+  return IP6_MIN_MTU_LENGTH; /* Minimum MTU */
 }
 
 
diff --git a/lwip/src/core/netif.c b/lwip/src/core/netif.c
index e432823..088b50e 100644
--- a/lwip/src/core/netif.c
+++ b/lwip/src/core/netif.c
@@ -72,7 +72,7 @@
 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
 #endif /* ENABLE_LOOPBACK */
 
-#include <netif/ethernet.h>
+#include "netif/ethernet.h"
 
 #if LWIP_AUTOIP
 #include "lwip/autoip.h"
@@ -348,10 +348,6 @@ netif_add(struct netif *netif,
 #if LWIP_IPV6 && LWIP_IPV6_MLD
   netif->mld_mac_filter = NULL;
 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
-#if ENABLE_LOOPBACK
-  netif->loop_first = NULL;
-  netif->loop_last = NULL;
-#endif /* ENABLE_LOOPBACK */
 
   /* remember netif specific state information data */
   netif->state = state;
@@ -359,9 +355,16 @@ netif_add(struct netif *netif,
   netif->input = input;
 
   NETIF_RESET_HINTS(netif);
-#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
+#if ENABLE_LOOPBACK
+  netif->loop_first = NULL;
+  netif->loop_last = NULL;
+#if LWIP_LOOPBACK_MAX_PBUFS
   netif->loop_cnt_current = 0;
-#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
+  netif->reschedule_poll = 0;
+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
+#endif /* ENABLE_LOOPBACK */
 
 #if LWIP_IPV4
   netif_set_addr(netif, ipaddr, netmask, gw);
@@ -1031,6 +1034,10 @@ netif_set_link_down(struct netif *netif)
 
   if (netif->flags & NETIF_FLAG_LINK_UP) {
     netif_clear_flags(netif, NETIF_FLAG_LINK_UP);
+#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
+    netif->mtu6 = netif->mtu;
+#endif
+
     NETIF_LINK_CALLBACK(netif);
 #if LWIP_NETIF_EXT_STATUS_CALLBACK
     {
@@ -1062,11 +1069,12 @@ netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callb
 /**
  * @ingroup netif
  * Send an IP packet to be received on the same netif (loopif-like).
- * The pbuf is simply copied and handed back to netif->input.
- * In multithreaded mode, this is done directly since netif->input must put
- * the packet on a queue.
- * In callback mode, the packet is put on an internal queue and is fed to
+ * The pbuf is copied and added to an internal queue which is fed to 
  * netif->input by netif_poll().
+ * In multithreaded mode, the call to netif_poll() is queued to be done on the
+ * TCP/IP thread.
+ * In callback mode, the user has the responsibility to call netif_poll() in 
+ * the main loop of their application.
  *
  * @param netif the lwip network interface structure
  * @param p the (IP) packet to 'send'
@@ -1143,6 +1151,12 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
     LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
     netif->loop_last->next = r;
     netif->loop_last = last;
+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
+    if (netif->reschedule_poll) {
+      schedule_poll = 1;
+      netif->reschedule_poll = 0;
+    }
+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
   } else {
     netif->loop_first = r;
     netif->loop_last = last;
@@ -1160,7 +1174,11 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
   /* For multithreading environment, schedule a call to netif_poll */
   if (schedule_poll) {
-    tcpip_try_callback((tcpip_callback_fn)netif_poll, netif);
+    if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) {
+      SYS_ARCH_PROTECT(lev);
+      netif->reschedule_poll = 1;
+      SYS_ARCH_UNPROTECT(lev);
+    }
   }
 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
 
@@ -1710,6 +1728,10 @@ netif_find(const char *name)
   }
 
   num = (u8_t)atoi(&name[2]);
+  if (!num && (name[2] != '0')) {
+    /* this means atoi has failed */
+    return NULL;
+  }
 
   NETIF_FOREACH(netif) {
     if (num == netif->num &&
diff --git a/lwip/src/core/pbuf.c b/lwip/src/core/pbuf.c
index a209e0c..7638dfd 100644
--- a/lwip/src/core/pbuf.c
+++ b/lwip/src/core/pbuf.c
@@ -271,7 +271,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
       break;
     }
     case PBUF_RAM: {
-      u16_t payload_len = (u16_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length));
+      mem_size_t payload_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length));
       mem_size_t alloc_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len);
 
       /* bug #50040: Check for integer overflow when calculating alloc_len */
@@ -960,54 +960,88 @@ pbuf_dechain(struct pbuf *p)
 err_t
 pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
 {
-  size_t offset_to = 0, offset_from = 0, len;
-
   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
               (const void *)p_to, (const void *)p_from));
 
+  LWIP_ERROR("pbuf_copy: invalid source", p_from != NULL, return ERR_ARG;);
+  return pbuf_copy_partial_pbuf(p_to, p_from, p_from->tot_len, 0);
+}
+
+/**
+ * @ingroup pbuf
+ * Copy part or all of one packet buffer into another, to a specified offset.
+ *
+ * @note Only data in one packet is copied, no packet queue!
+ * @note Argument order is shared with pbuf_copy, but different than pbuf_copy_partial.
+ *
+ * @param p_to pbuf destination of the copy
+ * @param p_from pbuf source of the copy
+ * @param copy_len number of bytes to copy
+ * @param offset offset in destination pbuf where to copy to
+ *
+ * @return ERR_OK if copy_len bytes were copied
+ *         ERR_ARG if one of the pbufs is NULL or p_from is shorter than copy_len
+ *                 or p_to is not big enough to hold copy_len at offset
+ *         ERR_VAL if any of the pbufs are part of a queue
+ */
+err_t
+pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
+{
+  size_t offset_to = offset, offset_from = 0, len_calc;
+  u16_t len;
+
+  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p, %"U16_F", %"U16_F")\n",
+              (const void *)p_to, (const void *)p_from, copy_len, offset));
+
+  /* is the copy_len in range? */
+  LWIP_ERROR("pbuf_copy_partial_pbuf: copy_len bigger than source", ((p_from != NULL) &&
+             (p_from->tot_len >= copy_len)), return ERR_ARG;);
   /* is the target big enough to hold the source? */
-  LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
-             (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
+  LWIP_ERROR("pbuf_copy_partial_pbuf: target not big enough", ((p_to != NULL) &&
+             (p_to->tot_len >= (offset + copy_len))), return ERR_ARG;);
 
   /* iterate through pbuf chain */
   do {
     /* copy one part of the original chain */
     if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
       /* complete current p_from fits into current p_to */
-      len = p_from->len - offset_from;
+      len_calc = p_from->len - offset_from;
     } else {
       /* current p_from does not fit into current p_to */
-      len = p_to->len - offset_to;
+      len_calc = p_to->len - offset_to;
     }
+    len = (u16_t)LWIP_MIN(copy_len, len_calc);
     MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len);
     offset_to += len;
     offset_from += len;
+    copy_len -= len;
     LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
     LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
     if (offset_from >= p_from->len) {
       /* on to next p_from (if any) */
       offset_from = 0;
       p_from = p_from->next;
+      LWIP_ERROR("p_from != NULL", (p_from != NULL) || (copy_len == 0), return ERR_ARG;);
     }
     if (offset_to == p_to->len) {
       /* on to next p_to (if any) */
       offset_to = 0;
       p_to = p_to->next;
-      LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return ERR_ARG;);
+      LWIP_ERROR("p_to != NULL", (p_to != NULL) || (copy_len == 0), return ERR_ARG;);
     }
 
     if ((p_from != NULL) && (p_from->len == p_from->tot_len)) {
       /* don't copy more than one packet! */
-      LWIP_ERROR("pbuf_copy() does not allow packet queues!",
+      LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
                  (p_from->next == NULL), return ERR_VAL;);
     }
     if ((p_to != NULL) && (p_to->len == p_to->tot_len)) {
       /* don't copy more than one packet! */
-      LWIP_ERROR("pbuf_copy() does not allow packet queues!",
+      LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
                  (p_to->next == NULL), return ERR_VAL;);
     }
-  } while (p_from);
-  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
+  } while (copy_len);
+  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf: copy complete.\n"));
   return ERR_OK;
 }
 
diff --git a/lwip/src/core/tcp.c b/lwip/src/core/tcp.c
index bd7d64e..11a51da 100644
--- a/lwip/src/core/tcp.c
+++ b/lwip/src/core/tcp.c
@@ -647,6 +647,7 @@ tcp_abort(struct tcp_pcb *pcb)
  * bound to all local IP addresses.
  * If another connection is bound to the same port, the function will
  * return ERR_USE, otherwise ERR_OK is returned.
+ * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
  *
  * @param pcb the tcp_pcb to bind (no check is done whether this pcb is
  *        already bound!)
@@ -1933,6 +1934,7 @@ tcp_alloc(u8_t prio)
  * any of the TCP PCB lists.
  * The pcb is not put on any list until binding using tcp_bind().
  * If memory is not available for creating the new pcb, NULL is returned.
+ * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
  *
  * @internal: Maybe there should be a idle TCP PCB list where these
  * PCBs are put on. Port reservation using tcp_bind() is implemented but
@@ -1952,6 +1954,7 @@ tcp_new(void)
  * Creates a new TCP protocol control block but doesn't
  * place it on any of the TCP PCB lists.
  * The pcb is not put on any list until binding using tcp_bind().
+ * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
  *
  * @param type IP address type, see @ref lwip_ip_addr_type definitions.
  * If you want to listen to IPv4 and IPv6 (dual-stack) connections,
@@ -2067,6 +2070,7 @@ tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
  * @ingroup tcp_raw
  * Used for specifying the function that should be called when a
  * LISTENing connection has been connected to another host.
+ * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB
  *
  * @param pcb tcp_pcb to set the accept callback
  * @param accept callback function to call for this pcb when LISTENing
diff --git a/lwip/src/core/tcp_in.c b/lwip/src/core/tcp_in.c
index 428a6f4..2202e38 100644
--- a/lwip/src/core/tcp_in.c
+++ b/lwip/src/core/tcp_in.c
@@ -852,8 +852,9 @@ tcp_process(struct tcp_pcb *pcb)
   /* Do different things depending on the TCP state. */
   switch (pcb->state) {
     case SYN_SENT:
-      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
-                                    pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno)));
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %s %"U32_F"\n",
+                                    ackno, pcb->snd_nxt, pcb->unacked ? "" : " empty:",
+                                    pcb->unacked ? lwip_ntohl(pcb->unacked->tcphdr->seqno) : 0));
       /* received SYN ACK with expected sequence number? */
       if ((flags & TCP_ACK) && (flags & TCP_SYN)
           && (ackno == pcb->lastack + 1)) {
diff --git a/lwip/src/core/tcp_out.c b/lwip/src/core/tcp_out.c
index 724df10..8149d39 100644
--- a/lwip/src/core/tcp_out.c
+++ b/lwip/src/core/tcp_out.c
@@ -913,6 +913,7 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
 
   seg = tcp_create_segment(pcb, p, remainder_flags, lwip_ntohl(useg->tcphdr->seqno) + split, optflags);
   if (seg == NULL) {
+    p = NULL; /* Freed by tcp_create_segment */
     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                 ("tcp_split_unsent_seg: could not create new TCP segment\n"));
     goto memerr;
@@ -2002,7 +2003,7 @@ tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno,
     LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
     return;
   }
-  tcp_output_fill_options(pcb, p, 0, optlen);
+  tcp_output_fill_options(pcb, p, 0, 0);
 
   MIB2_STATS_INC(mib2.tcpoutrsts);
 
@@ -2096,7 +2097,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
                 ("tcp_keepalive: could not allocate memory for pbuf\n"));
     return ERR_MEM;
   }
-  tcp_output_fill_options(pcb, p, 0, optlen);
+  tcp_output_fill_options(pcb, p, 0, 0);
   err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
 
   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n",
@@ -2178,7 +2179,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
   if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
     pcb->snd_nxt = snd_nxt;
   }
-  tcp_output_fill_options(pcb, p, 0, optlen);
+  tcp_output_fill_options(pcb, p, 0, 0);
 
   err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
 
diff --git a/lwip/src/core/udp.c b/lwip/src/core/udp.c
index 9d2cb4a..0b609d3 100644
--- a/lwip/src/core/udp.c
+++ b/lwip/src/core/udp.c
@@ -997,9 +997,13 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
         {
           /* port matches that of PCB in list and REUSEADDR not set -> reject */
           if ((ipcb->local_port == port) &&
+              (((IP_GET_TYPE(&ipcb->local_ip) == IP_GET_TYPE(ipaddr)) &&
               /* IP address matches or any IP used? */
-              (ip_addr_cmp(&ipcb->local_ip, ipaddr) || ip_addr_isany(ipaddr) ||
-              ip_addr_isany(&ipcb->local_ip))) {
+              (ip_addr_cmp(&ipcb->local_ip, ipaddr) ||
+              ip_addr_isany(ipaddr) ||
+              ip_addr_isany(&ipcb->local_ip))) ||
+              (IP_GET_TYPE(&ipcb->local_ip) == IPADDR_TYPE_ANY) ||
+              (IP_GET_TYPE(ipaddr) == IPADDR_TYPE_ANY))) {
             /* other PCB already binds to this local IP and port */
             LWIP_DEBUGF(UDP_DEBUG,
                         ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
@@ -1208,6 +1212,7 @@ udp_remove(struct udp_pcb *pcb)
  * Creates a new UDP pcb which can be used for UDP communication. The
  * pcb is not active until it has either been bound to a local address
  * or connected to a remote address.
+ * @see MEMP_NUM_UDP_PCB
  *
  * @return The UDP PCB which was created. NULL if the PCB data structure
  * could not be allocated.
@@ -1242,7 +1247,8 @@ udp_new(void)
  * Create a UDP PCB for specific IP type.
  * The pcb is not active until it has either been bound to a local address
  * or connected to a remote address.
- * 
+ * @see MEMP_NUM_UDP_PCB
+ *
  * @param type IP address type, see @ref lwip_ip_addr_type definitions.
  * If you want to listen to IPv4 and IPv6 (dual-stack) packets,
  * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
diff --git a/lwip/src/include/lwip/altcp.h b/lwip/src/include/lwip/altcp.h
index 97abc54..1b24544 100644
--- a/lwip/src/include/lwip/altcp.h
+++ b/lwip/src/include/lwip/altcp.h
@@ -129,6 +129,11 @@ err_t altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr,
 ip_addr_t *altcp_get_ip(struct altcp_pcb *conn, int local);
 u16_t altcp_get_port(struct altcp_pcb *conn, int local);
 
+#if LWIP_TCP_KEEPALIVE
+void  altcp_keepalive_disable(struct altcp_pcb *conn);
+void  altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count);
+#endif
+
 #ifdef LWIP_DEBUG
 enum tcp_state altcp_dbg_get_tcp_state(struct altcp_pcb *conn);
 #endif
diff --git a/lwip/src/include/lwip/altcp_tls.h b/lwip/src/include/lwip/altcp_tls.h
index 7b17c60..ff797f2 100644
--- a/lwip/src/include/lwip/altcp_tls.h
+++ b/lwip/src/include/lwip/altcp_tls.h
@@ -61,7 +61,22 @@ extern "C" {
 struct altcp_tls_config;
 
 /** @ingroup altcp_tls
- * Create an ALTCP_TLS server configuration handle
+ * Create an ALTCP_TLS server configuration handle prepared for multiple certificates
+ */
+struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count);
+
+/** @ingroup altcp_tls
+ * Add a certificate to an ALTCP_TLS server configuration handle
+ */
+err_t altcp_tls_config_server_add_privkey_cert(struct altcp_tls_config *config,
+      const u8_t *privkey, size_t privkey_len,
+      const u8_t *privkey_pass, size_t privkey_pass_len,
+      const u8_t *cert, size_t cert_len);
+
+/** @ingroup altcp_tls
+ * Create an ALTCP_TLS server configuration handle with one certificate
+ * (short version of calling @ref altcp_tls_create_config_server and
+ * @ref altcp_tls_config_server_add_privkey_cert)
  */
 struct altcp_tls_config *altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
                             const u8_t *privkey_pass, size_t privkey_pass_len,
@@ -84,6 +99,17 @@ struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca,
  */
 void altcp_tls_free_config(struct altcp_tls_config *conf);
 
+/** @ingroup altcp_tls
+ * Free an ALTCP_TLS global entropy instance.
+ * All ALTCP_TLS configuration are linked to one altcp_tls_entropy_rng structure
+ * that handle an unique system entropy & ctr_drbg instance.
+ * This function allow application to free this altcp_tls_entropy_rng structure
+ * when all configuration referencing it were destroyed.
+ * This function does nothing if some ALTCP_TLS configuration handle are still
+ * active.
+ */
+void altcp_tls_free_entropy(void);
+
 /** @ingroup altcp_tls
  * Create new ALTCP_TLS layer wrapping an existing pcb as inner connection (e.g. TLS over TCP)
  */
diff --git a/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h b/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h
index 36cddd9..71aa599 100644
--- a/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h
+++ b/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h
@@ -55,11 +55,49 @@
 #define ALTCP_MBEDTLS_DEBUG                           LWIP_DBG_OFF
 #endif
 
-/** Set a session timeout in seconds for the basic session cache
+/** Configure lwIP debug level of the mbedTLS library */
+#ifndef ALTCP_MBEDTLS_LIB_DEBUG
+#define ALTCP_MBEDTLS_LIB_DEBUG                       LWIP_DBG_OFF
+#endif
+
+/** Configure minimum internal debug level of the mbedTLS library */
+#ifndef ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN
+#define ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN             0
+#endif
+
+/** Enable the basic session cache
  * ATTENTION: Using a session cache can lower security by reusing keys!
  */
+#ifndef ALTCP_MBEDTLS_USE_SESSION_CACHE
+#define ALTCP_MBEDTLS_USE_SESSION_CACHE               0
+#endif
+
+/** Maximum cache size of the basic session cache */
+#ifndef ALTCP_MBEDTLS_SESSION_CACHE_SIZE
+#define ALTCP_MBEDTLS_SESSION_CACHE_SIZE              30
+#endif
+
+/** Set a session timeout in seconds for the basic session cache  */
 #ifndef ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
-#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS   0
+#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS   (60 * 60)
+#endif
+
+/** Use session tickets to speed up connection setup (needs
+ * MBEDTLS_SSL_SESSION_TICKETS enabled in mbedTLS config).
+ * ATTENTION: Using session tickets can lower security by reusing keys!
+ */
+#ifndef ALTCP_MBEDTLS_USE_SESSION_TICKETS
+#define ALTCP_MBEDTLS_USE_SESSION_TICKETS             0
+#endif
+
+/** Session ticket cipher */
+#ifndef ALTCP_MBEDTLS_SESSION_TICKET_CIPHER
+#define ALTCP_MBEDTLS_SESSION_TICKET_CIPHER           MBEDTLS_CIPHER_AES_256_GCM
+#endif
+
+/** Maximum timeout for session tickets */
+#ifndef ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS
+#define ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS  (60 * 60 * 24)
 #endif
 
 #endif /* LWIP_ALTCP */
diff --git a/lwip/src/include/lwip/apps/sntp.h b/lwip/src/include/lwip/apps/sntp.h
index 3c0f95f..c415253 100644
--- a/lwip/src/include/lwip/apps/sntp.h
+++ b/lwip/src/include/lwip/apps/sntp.h
@@ -67,11 +67,11 @@ void sntp_setservername(u8_t idx, const char *server);
 const char *sntp_getservername(u8_t idx);
 #endif /* SNTP_SERVER_DNS */
 
-#if SNTP_GET_SERVERS_FROM_DHCP
+#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6
 void sntp_servermode_dhcp(int set_servers_from_dhcp);
-#else /* SNTP_GET_SERVERS_FROM_DHCP */
+#else /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
 #define sntp_servermode_dhcp(x)
-#endif /* SNTP_GET_SERVERS_FROM_DHCP */
+#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
 
 #ifdef __cplusplus
 }
diff --git a/lwip/src/include/lwip/apps/sntp_opts.h b/lwip/src/include/lwip/apps/sntp_opts.h
index ed98040..cb62771 100644
--- a/lwip/src/include/lwip/apps/sntp_opts.h
+++ b/lwip/src/include/lwip/apps/sntp_opts.h
@@ -67,6 +67,12 @@
 #define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV
 #endif
 
+/** Set this to 1 to implement the callback function called by dhcpv6 when
+ * NTP servers are received. */
+#if !defined SNTP_GET_SERVERS_FROM_DHCPV6 || defined __DOXYGEN__
+#define SNTP_GET_SERVERS_FROM_DHCPV6 LWIP_DHCP6_GET_NTP_SRV
+#endif
+
 /** Set this to 1 to support DNS names (or IP address strings) to set sntp servers
  * One server address/name can be defined as default if SNTP_SERVER_DNS == 1:
  * \#define SNTP_SERVER_ADDRESS "pool.ntp.org"
diff --git a/lwip/src/include/lwip/debug.h b/lwip/src/include/lwip/debug.h
index baa6a40..579fd24 100644
--- a/lwip/src/include/lwip/debug.h
+++ b/lwip/src/include/lwip/debug.h
@@ -120,9 +120,7 @@
 #endif /* LWIP_NOASSERT */
 
 #ifndef LWIP_ERROR
-#ifndef LWIP_NOASSERT
-#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
-#elif defined LWIP_DEBUG
+#ifdef LWIP_DEBUG
 #define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message))
 #else
 #define LWIP_PLATFORM_ERROR(message)
diff --git a/lwip/src/include/lwip/if_api.h b/lwip/src/include/lwip/if_api.h
index 39017ab..b7269e2 100644
--- a/lwip/src/include/lwip/if_api.h
+++ b/lwip/src/include/lwip/if_api.h
@@ -49,7 +49,9 @@
 extern "C" {
 #endif
 
+#ifndef IF_NAMESIZE
 #define IF_NAMESIZE NETIF_NAMESIZE
+#endif
 
 char * lwip_if_indextoname(unsigned int ifindex, char *ifname);
 unsigned int lwip_if_nametoindex(const char *ifname);
diff --git a/lwip/src/include/lwip/init.h b/lwip/src/include/lwip/init.h
index a149be1..112ed86 100644
--- a/lwip/src/include/lwip/init.h
+++ b/lwip/src/include/lwip/init.h
@@ -54,11 +54,11 @@ extern "C" {
 /** x.X.x: Minor version of the stack */
 #define LWIP_VERSION_MINOR      1
 /** x.x.X: Revision of the stack */
-#define LWIP_VERSION_REVISION   2
+#define LWIP_VERSION_REVISION   3
 /** For release candidates, this is set to 1..254
   * For official releases, this is set to 255 (LWIP_RC_RELEASE)
   * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
-#define LWIP_VERSION_RC         LWIP_RC_RELEASE
+#define LWIP_VERSION_RC         1
 
 /** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
 #define LWIP_RC_RELEASE         255
diff --git a/lwip/src/include/lwip/netdb.h b/lwip/src/include/lwip/netdb.h
index ff33ec7..d3d15df 100644
--- a/lwip/src/include/lwip/netdb.h
+++ b/lwip/src/include/lwip/netdb.h
@@ -114,6 +114,11 @@ struct addrinfo {
 
 #define NETDB_ELEM_SIZE           (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1)
 
+#if LWIP_DNS_API_DECLARE_H_ERRNO
+/* application accessible error code set by the DNS API functions */
+extern int h_errno;
+#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/
+
 struct hostent *lwip_gethostbyname(const char *name);
 int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
                 size_t buflen, struct hostent **result, int *h_errnop);
@@ -123,64 +128,6 @@ int lwip_getaddrinfo(const char *nodename,
        const struct addrinfo *hints,
        struct addrinfo **res);
 
-const char *hstrerror(int err);
-
-#include "lwip/sockets.h"
-
-#define EAI_OVERFLOW 208
-
- struct servent {
-      char  *s_name;       /* official service name */
-      char **s_aliases;    /* alias list */
-      int    s_port;       /* port number */
-      char  *s_proto;      /* protocol to use */
-   };
-
-/*
- * Error return codes from getaddrinfo()
- */
- #define EAI_ADDRFAMILY   1      /* address family for hostname not supported */
- #define EAI_NODATA       7      /* no address associated with hostname */
- #define EAI_SOCKTYPE    10      /* ai_socktype not supported */
- #define EAI_SYSTEM      11      /* system 6rror returned in errno */
- #define EAI_BADHINTS    12
- #define EAI_PROTOCOL    13
- #define EAI_MAX         14
-
-/*
- * Constants for getnameinfo()
- */
-#define    NI_MAXHOST  1025
-#define    NI_MAXSERV  32
-
-/*
- * Flag values for getnameinfo()
- */
-#define    NI_NOFQDN   0x00000001
-#define    NI_NUMERICHOST  0x00000002
-#define    NI_NAMEREQD 0x00000004
-#define    NI_NUMERICSERV  0x00000008
-#define    NI_DGRAM    0x00000010
-#define NI_WITHSCOPEID 0x00000020
-
-#ifndef AF_UNIX
-#define    AF_UNIX     1
-#endif
-
-int
-getnameinfo(const struct sockaddr *sa, socklen_t salen,
-           char *host, size_t hostlen,
-           char *serv, size_t servlen, int flags);
-
-const char *gai_strerror(int ecode);
-
-struct servent *getservbyname(const char *name, const char *proto);
-
-#if LWIP_DNS_API_DECLARE_H_ERRNO
-/* application accessible error code set by the DNS API functions */
-extern int h_errno;
-#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/
-
 #if LWIP_COMPAT_SOCKETS
 /** @ingroup netdbapi */
 #define gethostbyname(name) lwip_gethostbyname(name)
@@ -194,8 +141,6 @@ extern int h_errno;
        lwip_getaddrinfo(nodname, servname, hints, res)
 #endif /* LWIP_COMPAT_SOCKETS */
 
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lwip/src/include/lwip/netif.h b/lwip/src/include/lwip/netif.h
index 911196a..9a16ded 100644
--- a/lwip/src/include/lwip/netif.h
+++ b/lwip/src/include/lwip/netif.h
@@ -386,6 +386,10 @@ struct netif {
 #if LWIP_LOOPBACK_MAX_PBUFS
   u16_t loop_cnt_current;
 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
+  /* Used if the original scheduling failed. */
+  u8_t reschedule_poll;
+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
 #endif /* ENABLE_LOOPBACK */
 };
 
@@ -451,7 +455,7 @@ void netif_set_gw(struct netif *netif, const ip4_addr_t *gw);
 
 #define netif_set_flags(netif, set_flags)     do { (netif)->flags = (u8_t)((netif)->flags |  (set_flags)); } while(0)
 #define netif_clear_flags(netif, clr_flags)   do { (netif)->flags = (u8_t)((netif)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0)
-#define netif_is_flag_set(nefif, flag)        (((netif)->flags & (flag)) != 0)
+#define netif_is_flag_set(netif, flag)        (((netif)->flags & (flag)) != 0)
 
 void netif_set_up(struct netif *netif);
 void netif_set_down(struct netif *netif);
diff --git a/lwip/src/include/lwip/opt.h b/lwip/src/include/lwip/opt.h
index 82c420c..d8c82d1 100644
--- a/lwip/src/include/lwip/opt.h
+++ b/lwip/src/include/lwip/opt.h
@@ -1545,7 +1545,7 @@
  * TCP_MSS, IP header, and link header.
  */
 #if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__
-#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
+#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS+PBUF_IP_HLEN+PBUF_TRANSPORT_HLEN+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
 #endif
 
 /**
@@ -1555,6 +1555,14 @@
 #if !defined LWIP_PBUF_REF_T || defined __DOXYGEN__
 #define LWIP_PBUF_REF_T                 u8_t
 #endif
+
+/**
+ * LWIP_PBUF_CUSTOM_DATA: Store private data on pbufs (e.g. timestamps)
+ * This extends struct pbuf so user can store custom data on every pbuf.
+ */
+#if !defined LWIP_PBUF_CUSTOM_DATA || defined __DOXYGEN__
+#define LWIP_PBUF_CUSTOM_DATA
+#endif
 /**
  * @}
  */
@@ -1912,11 +1920,8 @@
 
 /** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
  * writing from a 2nd thread and closing from a 3rd thread at the same time.
- * ATTENTION: This is currently really alpha! Some requirements:
- * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from
- *   multiple threads at once
- * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox
- *   and prevent a task pending on this during/after deletion
+ * LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from
+ * multiple threads at once!
  */
 #if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__
 #define LWIP_NETCONN_FULLDUPLEX         0
@@ -2446,7 +2451,7 @@
  * network startup.
  */
 #if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__
-#define LWIP_IPV6_SEND_ROUTER_SOLICIT   1
+#define LWIP_IPV6_SEND_ROUTER_SOLICIT   LWIP_IPV6
 #endif
 
 /**
@@ -2491,10 +2496,12 @@
 
 /**
  * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in
- * ICMPv6 error messages.
+ * ICMPv6 error messages (0 = default of IP6_MIN_MTU_LENGTH)
+ * ATTENTION: RFC4443 section 2.4 says IP6_MIN_MTU_LENGTH is a MUST,
+ * so override this only if you absolutely have to!
  */
 #if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__
-#define LWIP_ICMP6_DATASIZE             8
+#define LWIP_ICMP6_DATASIZE             0
 #endif
 
 /**
diff --git a/lwip/src/include/lwip/pbuf.h b/lwip/src/include/lwip/pbuf.h
index 82902a4..e5daf96 100644
--- a/lwip/src/include/lwip/pbuf.h
+++ b/lwip/src/include/lwip/pbuf.h
@@ -219,6 +219,9 @@ struct pbuf {
 
   /** For incoming packets, this contains the input netif's index */
   u8_t if_idx;
+
+  /** In case the user needs to store data custom data on a pbuf */
+  LWIP_PBUF_CUSTOM_DATA
 };
 
 
@@ -293,6 +296,7 @@ void pbuf_cat(struct pbuf *head, struct pbuf *tail);
 void pbuf_chain(struct pbuf *head, struct pbuf *tail);
 struct pbuf *pbuf_dechain(struct pbuf *p);
 err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from);
+err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset);
 u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
 void *pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset);
 err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
diff --git a/lwip/src/include/lwip/priv/altcp_priv.h b/lwip/src/include/lwip/priv/altcp_priv.h
index 2d3b2fd..d1de9b1 100644
--- a/lwip/src/include/lwip/priv/altcp_priv.h
+++ b/lwip/src/include/lwip/priv/altcp_priv.h
@@ -85,6 +85,11 @@ typedef err_t (*altcp_get_tcp_addrinfo_fn)(struct altcp_pcb *conn, int local, ip
 typedef ip_addr_t *(*altcp_get_ip_fn)(struct altcp_pcb *conn, int local);
 typedef u16_t (*altcp_get_port_fn)(struct altcp_pcb *conn, int local);
 
+#if LWIP_TCP_KEEPALIVE
+typedef void  (*altcp_keepalive_disable_fn)(struct altcp_pcb *conn);
+typedef void  (*altcp_keepalive_enable_fn)(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count);
+#endif
+
 #ifdef LWIP_DEBUG
 typedef enum tcp_state (*altcp_dbg_get_tcp_state_fn)(struct altcp_pcb *conn);
 #endif
@@ -111,6 +116,10 @@ struct altcp_functions {
   altcp_get_tcp_addrinfo_fn   addrinfo;
   altcp_get_ip_fn             getip;
   altcp_get_port_fn           getport;
+#if LWIP_TCP_KEEPALIVE
+  altcp_keepalive_disable_fn  keepalive_disable;
+  altcp_keepalive_enable_fn   keepalive_enable;
+#endif
 #ifdef LWIP_DEBUG
   altcp_dbg_get_tcp_state_fn  dbg_get_tcp_state;
 #endif
@@ -133,6 +142,10 @@ void  altcp_default_dealloc(struct altcp_pcb *conn);
 err_t altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port);
 ip_addr_t *altcp_default_get_ip(struct altcp_pcb *conn, int local);
 u16_t altcp_default_get_port(struct altcp_pcb *conn, int local);
+#if LWIP_TCP_KEEPALIVE
+void  altcp_default_keepalive_disable(struct altcp_pcb *conn);
+void  altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count);
+#endif
 #ifdef LWIP_DEBUG
 enum tcp_state altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn);
 #endif
diff --git a/lwip/src/include/lwip/prot/icmp6.h b/lwip/src/include/lwip/prot/icmp6.h
index 3461120..36989f6 100644
--- a/lwip/src/include/lwip/prot/icmp6.h
+++ b/lwip/src/include/lwip/prot/icmp6.h
@@ -146,6 +146,8 @@ PACK_STRUCT_END
 #  include "arch/epstruct.h"
 #endif
 
+#define ICMP6_HLEN 8
+
 /** This is the ICMP6 header adapted for echo req/resp. */
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
diff --git a/lwip/src/include/lwip/prot/ip6.h b/lwip/src/include/lwip/prot/ip6.h
index 0f6de45..7df81ed 100644
--- a/lwip/src/include/lwip/prot/ip6.h
+++ b/lwip/src/include/lwip/prot/ip6.h
@@ -44,6 +44,8 @@
 extern "C" {
 #endif
 
+#define IP6_MIN_MTU_LENGTH 1280
+
 /** This is the packed version of ip6_addr_t,
     used in network headers that are itself packed */
 #ifdef PACK_STRUCT_USE_INCLUDES
diff --git a/lwip/src/include/lwip/sys.h b/lwip/src/include/lwip/sys.h
index 1933590..168e465 100644
--- a/lwip/src/include/lwip/sys.h
+++ b/lwip/src/include/lwip/sys.h
@@ -38,7 +38,6 @@
 #define LWIP_HDR_SYS_H
 
 #include "lwip/opt.h"
-#include "arch/sys_arch.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/lwip/src/include/netif/ppp/ppp_opts.h b/lwip/src/include/netif/ppp/ppp_opts.h
index 6702bec..479a006 100644
--- a/lwip/src/include/netif/ppp/ppp_opts.h
+++ b/lwip/src/include/netif/ppp/ppp_opts.h
@@ -44,6 +44,13 @@
 #define PPPOE_SUPPORT                   0
 #endif
 
+/**
+ * PPPOE_SCNAME_SUPPORT==1: Enable PPP Over Ethernet Service Name and Concentrator Name support
+ */
+#ifndef PPPOE_SCNAME_SUPPORT
+#define PPPOE_SCNAME_SUPPORT            0
+#endif
+
 /**
  * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP
  */
diff --git a/lwip/src/include/netif/ppp/pppoe.h b/lwip/src/include/netif/ppp/pppoe.h
index 08ab7ab..8994d38 100644
--- a/lwip/src/include/netif/ppp/pppoe.h
+++ b/lwip/src/include/netif/ppp/pppoe.h
@@ -149,10 +149,10 @@ struct pppoe_softc {
   u16_t sc_session;            /* PPPoE session id */
   u8_t sc_state;               /* discovery phase or session connected */
 
-#ifdef PPPOE_TODO
-  u8_t *sc_service_name;       /* if != NULL: requested name of service */
-  u8_t *sc_concentrator_name;  /* if != NULL: requested concentrator id */
-#endif /* PPPOE_TODO */
+#if PPPOE_SCNAME_SUPPORT
+  const char *sc_service_name;      /* if != NULL: requested name of service */
+  const char *sc_concentrator_name; /* if != NULL: requested concentrator id */
+#endif /* PPPOE_SCNAME_SUPPORT */
   u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */
   u8_t sc_ac_cookie_len;       /* length of cookie data */
 #ifdef PPPOE_SERVER
diff --git a/lwip/src/netif/ethernet.c b/lwip/src/netif/ethernet.c
index bd32201..dd171e2 100644
--- a/lwip/src/netif/ethernet.c
+++ b/lwip/src/netif/ethernet.c
@@ -40,7 +40,7 @@
 
 #include "lwip/opt.h"
 
-#ifdef LWIP_ETHERNET
+#if LWIP_ARP || LWIP_ETHERNET
 
 #include "netif/ethernet.h"
 #include "lwip/def.h"
diff --git a/lwip/src/netif/lowpan6.c b/lwip/src/netif/lowpan6.c
index 7f0d276..5e6f009 100644
--- a/lwip/src/netif/lowpan6.c
+++ b/lwip/src/netif/lowpan6.c
@@ -881,7 +881,7 @@ lowpan6_if_init(struct netif *netif)
   MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
 
   /* maximum transfer unit */
-  netif->mtu = 1280;
+  netif->mtu = IP6_MIN_MTU_LENGTH;
 
   /* broadcast capability */
   netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */;
diff --git a/lwip/src/netif/lowpan6_ble.c b/lwip/src/netif/lowpan6_ble.c
index d89816d..6de0ae3 100644
--- a/lwip/src/netif/lowpan6_ble.c
+++ b/lwip/src/netif/lowpan6_ble.c
@@ -417,7 +417,7 @@ rfc7668_if_init(struct netif *netif)
   MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
 
   /* maximum transfer unit, set according to RFC7668 ch2.4 */
-  netif->mtu = 1280;
+  netif->mtu = IP6_MIN_MTU_LENGTH;
 
   /* no flags set (no broadcast, ethernet,...)*/
   netif->flags = 0;
diff --git a/lwip/src/netif/lowpan6_common.c b/lwip/src/netif/lowpan6_common.c
index baea206..4db1ebb 100644
--- a/lwip/src/netif/lowpan6_common.c
+++ b/lwip/src/netif/lowpan6_common.c
@@ -440,7 +440,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
   if ((lowpan6_buffer[0] & 0x18) == 0x00) {
     header_temp = ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | \
       (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3];
-    LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%2x, Flowlabel+DSCP: 0x%8X\n", \
+    LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%"X8_F", Flowlabel+DSCP: 0x%8"X32_F"\n", \
       lowpan6_buffer[lowpan6_offset],header_temp));
     IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], header_temp);
     /* increase offset, processed 4 bytes here:
@@ -448,14 +448,14 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
     lowpan6_offset += 4;
   } else if ((lowpan6_buffer[0] & 0x18) == 0x08) {
     header_temp = ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2];
-    LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%2x, Flowlabel: 0x%2X, DSCP ignored\n", \
+    LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%"X8_F", Flowlabel: 0x%2"X32_F", DSCP ignored\n", \
       lowpan6_buffer[lowpan6_offset] & 0xc0,header_temp));
     IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, header_temp);
     /* increase offset, processed 3 bytes here:
      * TF=01:  ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided.*/
     lowpan6_offset += 3;
   } else if ((lowpan6_buffer[0] & 0x18) == 0x10) {
-    LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%2x, Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset]));
+    LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%"X8_F", Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset]));
     IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0);
     /* increase offset, processed 1 byte here:
      * ECN + DSCP (1 byte), Flow Label is elided.*/
@@ -564,7 +564,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize,
 #if LWIP_6LOWPAN_NUM_CONTEXTS > 0
       ip6hdr->src.addr[0] = lowpan6_contexts[i].addr[0];
       ip6hdr->src.addr[1] = lowpan6_contexts[i].addr[1];
-      LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8X, %8X\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1]));
+      LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8"X32_F", %8"X32_F"\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1]));
 #else
       LWIP_UNUSED_ARG(lowpan6_contexts);
 #endif
diff --git a/lwip/src/netif/ppp/pppoe.c b/lwip/src/netif/ppp/pppoe.c
index 8ed2d63..971b36b 100644
--- a/lwip/src/netif/ppp/pppoe.c
+++ b/lwip/src/netif/ppp/pppoe.c
@@ -175,8 +175,10 @@ ppp_pcb *pppoe_create(struct netif *pppif,
 {
   ppp_pcb *ppp;
   struct pppoe_softc *sc;
+#if !PPPOE_SCNAME_SUPPORT
   LWIP_UNUSED_ARG(service_name);
   LWIP_UNUSED_ARG(concentrator_name);
+#endif /* !PPPOE_SCNAME_SUPPORT */
   LWIP_ASSERT_CORE_LOCKED();
 
   sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF);
@@ -193,6 +195,10 @@ ppp_pcb *pppoe_create(struct netif *pppif,
   memset(sc, 0, sizeof(struct pppoe_softc));
   sc->pcb = ppp;
   sc->sc_ethif = ethif;
+#if PPPOE_SCNAME_SUPPORT
+  sc->sc_service_name = service_name;
+  sc->sc_concentrator_name = concentrator_name;
+#endif /* PPPOE_SCNAME_SUPPORT */
   /* put the new interface at the head of the list */
   sc->next = pppoe_softc_list;
   pppoe_softc_list = sc;
@@ -300,15 +306,6 @@ pppoe_destroy(ppp_pcb *ppp, void *ctx)
        break;
     }
   }
-
-#ifdef PPPOE_TODO
-  if (sc->sc_concentrator_name) {
-    mem_free(sc->sc_concentrator_name);
-  }
-  if (sc->sc_service_name) {
-    mem_free(sc->sc_service_name);
-  }
-#endif /* PPPOE_TODO */
   LWIP_MEMPOOL_FREE(PPPOE_IF, sc);
 
   return ERR_OK;
@@ -757,13 +754,13 @@ pppoe_send_padi(struct pppoe_softc *sc)
   struct pbuf *pb;
   u8_t *p;
   int len;
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   int l1 = 0, l2 = 0; /* XXX: gcc */
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
 
   /* calculate length of frame (excluding ethernet header + pppoe header) */
   len = 2 + 2 + 2 + 2 + sizeof sc;  /* service name tag is required, host unique is send too */
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   if (sc->sc_service_name != NULL) {
     l1 = (int)strlen(sc->sc_service_name);
     len += l1;
@@ -772,7 +769,7 @@ pppoe_send_padi(struct pppoe_softc *sc)
     l2 = (int)strlen(sc->sc_concentrator_name);
     len += 2 + 2 + l2;
   }
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
   LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
     sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
 
@@ -787,24 +784,24 @@ pppoe_send_padi(struct pppoe_softc *sc)
   /* fill in pkt */
   PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len);
   PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   if (sc->sc_service_name != NULL) {
     PPPOE_ADD_16(p, l1);
     MEMCPY(p, sc->sc_service_name, l1);
     p += l1;
   } else
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
   {
     PPPOE_ADD_16(p, 0);
   }
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   if (sc->sc_concentrator_name != NULL) {
     PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
     PPPOE_ADD_16(p, l2);
     MEMCPY(p, sc->sc_concentrator_name, l2);
     p += l2;
   }
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
   PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
   PPPOE_ADD_16(p, sizeof(sc));
   MEMCPY(p, &sc, sizeof sc);
@@ -982,17 +979,17 @@ pppoe_send_padr(struct pppoe_softc *sc)
   struct pbuf *pb;
   u8_t *p;
   size_t len;
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   size_t l1 = 0; /* XXX: gcc */
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
 
   len = 2 + 2 + 2 + 2 + sizeof(sc);    /* service name, host unique */
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   if (sc->sc_service_name != NULL) {    /* service name tag maybe empty */
     l1 = strlen(sc->sc_service_name);
     len += l1;
   }
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
   if (sc->sc_ac_cookie_len > 0) {
     len += 2 + 2 + sc->sc_ac_cookie_len;  /* AC cookie */
   }
@@ -1006,13 +1003,13 @@ pppoe_send_padr(struct pppoe_softc *sc)
   p = (u8_t*)pb->payload;
   PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
   PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
-#ifdef PPPOE_TODO
+#if PPPOE_SCNAME_SUPPORT
   if (sc->sc_service_name != NULL) {
     PPPOE_ADD_16(p, l1);
     MEMCPY(p, sc->sc_service_name, l1);
     p += l1;
   } else
-#endif /* PPPOE_TODO */
+#endif /* PPPOE_SCNAME_SUPPORT */
   {
     PPPOE_ADD_16(p, 0);
   }
diff --git a/lwip/src/netif/zepif.c b/lwip/src/netif/zepif.c
index b403303..de43b99 100644
--- a/lwip/src/netif/zepif.c
+++ b/lwip/src/netif/zepif.c
@@ -201,7 +201,7 @@ zepif_linkoutput(struct netif *netif, struct pbuf *p)
   state->seqno++;
   zep->len = (u8_t)p->tot_len;
 
-  err = pbuf_take_at(q, p->payload, p->tot_len, sizeof(struct zep_hdr));
+  err = pbuf_copy_partial_pbuf(q, p, p->tot_len, sizeof(struct zep_hdr));
   if (err == ERR_OK) {
 #if ZEPIF_LOOPBACK
     zepif_udp_recv(netif, state->pcb, pbuf_clone(PBUF_RAW, PBUF_RAM, q), NULL, 0);
diff --git a/lwip/ports/os/lwipopts.h b/lwip/test/lwipopts.h
similarity index 100%
rename from lwip/ports/os/lwipopts.h
rename to lwip/test/lwipopts.h
diff --git a/wscript b/wscript
index 0393e8c..48ea861 100644
--- a/wscript
+++ b/wscript
@@ -46,9 +46,11 @@ def init(ctx):
 
 def options(opt):
     rtems.options(opt)
+    lwip.options(opt)
 
 
 def configure(conf):
+    lwip.configure(conf)
     rtems.configure(conf)
 
 
-- 
2.32.0



More information about the devel mailing list