From fc88922845fc1cab9f7eaff573d5036175bf590d Mon Sep 17 00:00:00 2001 From: Tymoteusz Bloch Date: Wed, 14 Nov 2018 13:50:36 +0100 Subject: [PATCH] L3IP Interface Implementation LWIP L3IP interface initial implementatioon --- features/lwipstack/LWIPInterface.cpp | 54 +++++ features/lwipstack/LWIPInterfaceL3IP.cpp | 166 ++++++++++++++++ features/lwipstack/LWIPMemoryManager.cpp | 30 +-- features/lwipstack/LWIPMemoryManager.h | 25 +-- features/lwipstack/LWIPStack.h | 44 ++++- features/lwipstack/lwipopts.h | 1 + features/netsocket/EMACMemoryManager.h | 142 +------------ features/netsocket/L3IP.h | 158 +++++++++++++++ features/netsocket/L3IPInterface.cpp | 140 +++++++++++++ features/netsocket/L3IPInterface.h | 161 +++++++++++++++ ...yManager.cpp => NetStackMemoryManager.cpp} | 10 +- features/netsocket/NetStackMemoryManager.h | 187 ++++++++++++++++++ features/netsocket/OnboardNetworkStack.h | 11 ++ .../cellular/cellular_driver_l3ip.cpp | 121 ++++++++++++ .../netsocket/cellular/cellular_driver_l3ip.h | 135 +++++++++++++ features/netsocket/nsapi_types.h | 4 + 16 files changed, 1217 insertions(+), 172 deletions(-) create mode 100644 features/lwipstack/LWIPInterfaceL3IP.cpp create mode 100644 features/netsocket/L3IP.h create mode 100644 features/netsocket/L3IPInterface.cpp create mode 100644 features/netsocket/L3IPInterface.h rename features/netsocket/{EMACMemoryManager.cpp => NetStackMemoryManager.cpp} (82%) create mode 100644 features/netsocket/NetStackMemoryManager.h create mode 100644 features/netsocket/cellular/cellular_driver_l3ip.cpp create mode 100644 features/netsocket/cellular/cellular_driver_l3ip.h diff --git a/features/lwipstack/LWIPInterface.cpp b/features/lwipstack/LWIPInterface.cpp index c1c1861534..9bbfaa82fd 100644 --- a/features/lwipstack/LWIPInterface.cpp +++ b/features/lwipstack/LWIPInterface.cpp @@ -409,6 +409,60 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN #endif //LWIP_ETHERNET } + +nsapi_error_t LWIP::add_l3ip_interface(L3IP &l3ip, bool default_if, OnboardNetworkStack::Interface **interface_out) +{ +#if LWIP_L3IP + Interface *interface = new (std::nothrow) Interface(); + if (!interface) { + return NSAPI_ERROR_NO_MEMORY; + } + interface->l3ip = &l3ip; + interface->memory_manager = &memory_manager; + interface->ppp = false; + + + + // interface->netif.hwaddr_len = 0; should we set? + + if (!netif_add(&interface->netif, +#if LWIP_IPV4 + 0, 0, 0, +#endif + interface, &LWIP::Interface::emac_if_init, ip_input)) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + if (default_if) { + netif_set_default(&interface->netif); + default_interface = interface; + } + + netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq); + netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq); + + *interface_out = interface; + + + //lwip_add_random_seed(seed); to do? + + return NSAPI_ERROR_OK; + +#else + return NSAPI_ERROR_UNSUPPORTED; + +#endif //LWIP_L3IP +} + +nsapi_error_t LWIP::remove_l3ip_interface(OnboardNetworkStack::Interface **interface_out) +{ +#if LWIP_L3IP + return NSAPI_ERROR_OK; +#else + return NSAPI_ERROR_UNSUPPORTED; + +#endif //LWIP_L3IP +} /* Internal API to preserve existing PPP functionality - revise to better match mbed_ipstak_add_ethernet_interface later */ nsapi_error_t LWIP::_add_ppp_interface(void *hw, bool default_if, nsapi_ip_stack_t stack, LWIP::Interface **interface_out) { diff --git a/features/lwipstack/LWIPInterfaceL3IP.cpp b/features/lwipstack/LWIPInterfaceL3IP.cpp new file mode 100644 index 0000000000..e15e553fc4 --- /dev/null +++ b/features/lwipstack/LWIPInterfaceL3IP.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lwip/tcpip.h" +#include "lwip/tcp.h" +#include "lwip/ip.h" +#include "netif/etharp.h" +#include "lwip/ethip6.h" +#include "netsocket/nsapi_types.h" +#include "netsocket/L3IP.h" + +#include "LWIPStack.h" + +#if LWIP_L3IP + +err_t LWIP::Interface::l3ip_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + /* Increase reference counter since lwip stores handle to pbuf and frees + it after output */ + pbuf_ref(p); + + LWIP::Interface *mbed_if = static_cast(netif->state); + bool ret = mbed_if->l3ip->link_out(p); + return ret ? ERR_OK : ERR_IF; +} + +void LWIP::Interface::l3ip_input(net_stack_mem_buf_t *buf) +{ + struct pbuf *p = static_cast(buf); + + /* pass all packets to IP stack input */ + if (netif.input(p, &netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("Emac LWIP: IP input error\n")); + + pbuf_free(p); + } +} + +void LWIP::Interface::l3ip_state_change(bool up) +{ + if (up) { + tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, &netif, 1); + } else { + tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, &netif, 1); + } +} + +#if LWIP_IGMP + +#include "lwip/igmp.h" +/** + * IPv4 address filtering setup. + * + * \param[in] netif the lwip network interface structure + * \param[in] group IPv4 group to modify + * \param[in] action + * \return ERR_OK or error code + */ +err_t LWIP::Interface::l3ip_multicast_ipv4_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action) +{ + LWIP::Interface *mbed_if = static_cast(netif->state); + SocketAddress addr(&group, NSAPI_IPv6); + switch (action) { + case NETIF_ADD_MAC_FILTER: { + mbed_if->l3ip->add_ipv4_multicast_group(addr.get_ip_address()); + return ERR_OK; + } + case NETIF_DEL_MAC_FILTER: + mbed_if->l3ip->remove_ipv4_multicast_group(addr.get_ip_address()); + return ERR_OK; + default: + return ERR_ARG; + } + +} +#endif + +#if LWIP_IPV6_MLD + +#include "lwip/mld6.h" +/** + * IPv6 address filtering setup. + * + * \param[in] netif the lwip network interface structure + * \param[in] group IPv6 group to modify + * \param[in] action + * \return ERR_OK or error code + */ +err_t LWIP::Interface::l3ip_multicast_ipv6_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action) +{ + LWIP::Interface *mbed_if = static_cast(netif->state); + SocketAddress addr(&group, NSAPI_IPv6); + switch (action) { + case NETIF_ADD_MAC_FILTER: { + + mbed_if->l3ip->add_ipv6_multicast_group(addr.get_ip_address()); + return ERR_OK; + } + case NETIF_DEL_MAC_FILTER: + mbed_if->l3ip->remove_ipv6_multicast_group(addr.get_ip_address()); + return ERR_OK; + default: + return ERR_ARG; + } + +} +#endif + +err_t LWIP::Interface::l3ip_if_init(struct netif *netif) +{ + int err = ERR_OK; + LWIP::Interface *mbed_if = static_cast(netif->state); + + mbed_if->l3ip->set_memory_manager(*mbed_if->memory_manager); + mbed_if->l3ip->set_link_input_cb(mbed::callback(mbed_if, &LWIP::Interface::l3ip_input)); + mbed_if->l3ip->set_link_state_cb(mbed::callback(mbed_if, &LWIP::Interface::l3ip_state_change)); + + /* Interface capabilities */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET; + + if (!mbed_if->l3ip->power_up()) { + err = ERR_IF; + } + + netif->mtu = mbed_if->l3ip->get_mtu_size(); + mbed_if->l3ip->get_ifname(netif->name, NSAPI_INTERFACE_NAME_SIZE); + +#if LWIP_IPV4 + netif->output = &LWIP::Interface::l3ip_output; +#if LWIP_IGMP + netif->igmp_mac_filter = &LWIP::Interface::l3ip_multicast_ipv4_filter; + netif->flags |= NETIF_FLAG_IGMP; +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + //netif->output_ip6 = ethip6_output;//to be done +#if LWIP_IPV6_MLD + netif->mld_mac_filter = &LWIP::Interface::l3ip_multicast_ipv6_filter; + netif->flags |= NETIF_FLAG_MLD6; +#else +// Would need to enable all multicasts here - no API in fsl_enet to do that +#error "IPv6 multicasts won't be received if LWIP_IPV6_MLD is disabled, breaking the system" +#endif +#endif + + netif->linkoutput = NULL; + + return err; +} + +#endif + diff --git a/features/lwipstack/LWIPMemoryManager.cpp b/features/lwipstack/LWIPMemoryManager.cpp index 6490965702..678cc23f58 100644 --- a/features/lwipstack/LWIPMemoryManager.cpp +++ b/features/lwipstack/LWIPMemoryManager.cpp @@ -16,7 +16,7 @@ #include "pbuf.h" #include "LWIPMemoryManager.h" -emac_mem_buf_t *LWIPMemoryManager::alloc_heap(uint32_t size, uint32_t align) +net_stack_mem_buf_t *LWIPMemoryManager::alloc_heap(uint32_t size, uint32_t align) { struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, size + align, PBUF_RAM); if (pbuf == NULL) { @@ -25,10 +25,10 @@ emac_mem_buf_t *LWIPMemoryManager::alloc_heap(uint32_t size, uint32_t align) align_memory(pbuf, align); - return static_cast(pbuf); + return static_cast(pbuf); } -emac_mem_buf_t *LWIPMemoryManager::alloc_pool(uint32_t size, uint32_t align) +net_stack_mem_buf_t *LWIPMemoryManager::alloc_pool(uint32_t size, uint32_t align) { uint32_t total_align = count_total_align(size, align); @@ -39,7 +39,7 @@ emac_mem_buf_t *LWIPMemoryManager::alloc_pool(uint32_t size, uint32_t align) align_memory(pbuf, align); - return static_cast(pbuf); + return static_cast(pbuf); } uint32_t LWIPMemoryManager::get_pool_alloc_unit(uint32_t align) const @@ -48,56 +48,56 @@ uint32_t LWIPMemoryManager::get_pool_alloc_unit(uint32_t align) const return alloc_unit; } -void LWIPMemoryManager::free(emac_mem_buf_t *buf) +void LWIPMemoryManager::free(net_stack_mem_buf_t *buf) { pbuf_free(static_cast(buf)); } -uint32_t LWIPMemoryManager::get_total_len(const emac_mem_buf_t *buf) const +uint32_t LWIPMemoryManager::get_total_len(const net_stack_mem_buf_t *buf) const { return (static_cast(buf))->tot_len; } -void LWIPMemoryManager::copy(emac_mem_buf_t *to_buf, const emac_mem_buf_t *from_buf) +void LWIPMemoryManager::copy(net_stack_mem_buf_t *to_buf, const net_stack_mem_buf_t *from_buf) { pbuf_copy(static_cast(to_buf), static_cast(from_buf)); } -void LWIPMemoryManager::copy_to_buf(emac_mem_buf_t *to_buf, const void *ptr, uint32_t len) +void LWIPMemoryManager::copy_to_buf(net_stack_mem_buf_t *to_buf, const void *ptr, uint32_t len) { pbuf_take(static_cast(to_buf), ptr, len); } -uint32_t LWIPMemoryManager::copy_from_buf(void *ptr, uint32_t len, const emac_mem_buf_t *from_buf) const +uint32_t LWIPMemoryManager::copy_from_buf(void *ptr, uint32_t len, const net_stack_mem_buf_t *from_buf) const { return pbuf_copy_partial(static_cast(from_buf), ptr, len, 0); } -void LWIPMemoryManager::cat(emac_mem_buf_t *to_buf, emac_mem_buf_t *cat_buf) +void LWIPMemoryManager::cat(net_stack_mem_buf_t *to_buf, net_stack_mem_buf_t *cat_buf) { pbuf_cat(static_cast(to_buf), static_cast(cat_buf)); } -emac_mem_buf_t *LWIPMemoryManager::get_next(const emac_mem_buf_t *buf) const +net_stack_mem_buf_t *LWIPMemoryManager::get_next(const net_stack_mem_buf_t *buf) const { if (!buf) { return NULL; } struct pbuf *next = (static_cast(buf))->next; - return static_cast(next); + return static_cast(next); } -void *LWIPMemoryManager::get_ptr(const emac_mem_buf_t *buf) const +void *LWIPMemoryManager::get_ptr(const net_stack_mem_buf_t *buf) const { return (static_cast(buf))->payload; } -uint32_t LWIPMemoryManager::get_len(const emac_mem_buf_t *buf) const +uint32_t LWIPMemoryManager::get_len(const net_stack_mem_buf_t *buf) const { return (static_cast(buf))->len; } -void LWIPMemoryManager::set_len(emac_mem_buf_t *buf, uint32_t len) +void LWIPMemoryManager::set_len(net_stack_mem_buf_t *buf, uint32_t len) { struct pbuf *pbuf = static_cast(buf); pbuf->len = len; diff --git a/features/lwipstack/LWIPMemoryManager.h b/features/lwipstack/LWIPMemoryManager.h index 5ecf98b4d4..74cfa5f1a8 100644 --- a/features/lwipstack/LWIPMemoryManager.h +++ b/features/lwipstack/LWIPMemoryManager.h @@ -18,6 +18,7 @@ #include "EMACMemoryManager.h" + class LWIPMemoryManager : public EMACMemoryManager { public: @@ -30,7 +31,7 @@ public: * @param align Memory alignment requirement in bytes * @return Allocated memory buffer, or NULL in case of error */ - virtual emac_mem_buf_t *alloc_heap(uint32_t size, uint32_t align); + virtual net_stack_mem_buf_t *alloc_heap(uint32_t size, uint32_t align); /** * Allocates memory buffer chain from a pool @@ -43,7 +44,7 @@ public: * @param align Memory alignment requirement for each buffer in bytes * @return Allocated memory buffer chain, or NULL in case of error */ - virtual emac_mem_buf_t *alloc_pool(uint32_t size, uint32_t align); + virtual net_stack_mem_buf_t *alloc_pool(uint32_t size, uint32_t align); /** * Get memory buffer pool allocation unit @@ -63,7 +64,7 @@ public: * * @param buf Memory buffer chain to be freed. */ - virtual void free(emac_mem_buf_t *buf); + virtual void free(net_stack_mem_buf_t *buf); /** * Return total length of a memory buffer chain @@ -73,7 +74,7 @@ public: * @param buf Memory buffer chain * @return Total length in bytes */ - virtual uint32_t get_total_len(const emac_mem_buf_t *buf) const; + virtual uint32_t get_total_len(const net_stack_mem_buf_t *buf) const; /** * Copy a memory buffer chain @@ -84,7 +85,7 @@ public: * @param to_buf Memory buffer chain to copy to * @param from_buf Memory buffer chain to copy from */ - virtual void copy(emac_mem_buf_t *to_buf, const emac_mem_buf_t *from_buf); + virtual void copy(net_stack_mem_buf_t *to_buf, const net_stack_mem_buf_t *from_buf); /** * Copy to a memory buffer chain @@ -97,7 +98,7 @@ public: * @param ptr Pointer to data * @param len Data length */ - virtual void copy_to_buf(emac_mem_buf_t *to_buf, const void *ptr, uint32_t len); + virtual void copy_to_buf(net_stack_mem_buf_t *to_buf, const void *ptr, uint32_t len); /** * Copy from a memory buffer chain @@ -109,7 +110,7 @@ public: * @param from_buf Memory buffer chain to copy from * @return Length of the data that was copied */ - virtual uint32_t copy_from_buf(void *ptr, uint32_t len, const emac_mem_buf_t *from_buf) const; + virtual uint32_t copy_from_buf(void *ptr, uint32_t len, const net_stack_mem_buf_t *from_buf) const; /** * Concatenate two memory buffer chains @@ -121,7 +122,7 @@ public: * @param to_buf Memory buffer chain to concatenate to * @param cat_buf Memory buffer chain to concatenate */ - virtual void cat(emac_mem_buf_t *to_buf, emac_mem_buf_t *cat_buf); + virtual void cat(net_stack_mem_buf_t *to_buf, net_stack_mem_buf_t *cat_buf); /** * Returns the next buffer @@ -131,7 +132,7 @@ public: * @param buf Memory buffer * @return The next memory buffer, or NULL if last */ - virtual emac_mem_buf_t *get_next(const emac_mem_buf_t *buf) const; + virtual net_stack_mem_buf_t *get_next(const net_stack_mem_buf_t *buf) const; /** * Return pointer to the payload of the buffer @@ -139,7 +140,7 @@ public: * @param buf Memory buffer * @return Pointer to the payload */ - virtual void *get_ptr(const emac_mem_buf_t *buf) const; + virtual void *get_ptr(const net_stack_mem_buf_t *buf) const; /** * Return payload size of the buffer @@ -147,7 +148,7 @@ public: * @param buf Memory buffer * @return Size in bytes */ - virtual uint32_t get_len(const emac_mem_buf_t *buf) const; + virtual uint32_t get_len(const net_stack_mem_buf_t *buf) const; /** * Sets the payload size of the buffer @@ -158,7 +159,7 @@ public: * @param buf Memory buffer * @param len Payload size, must be less or equal allocated size */ - virtual void set_len(emac_mem_buf_t *buf, uint32_t len); + virtual void set_len(net_stack_mem_buf_t *buf, uint32_t len); private: diff --git a/features/lwipstack/LWIPStack.h b/features/lwipstack/LWIPStack.h index c35c3c239d..f86eff774b 100644 --- a/features/lwipstack/LWIPStack.h +++ b/features/lwipstack/LWIPStack.h @@ -25,6 +25,7 @@ #include "lwip/ethip6.h" #include "netsocket/nsapi_types.h" #include "netsocket/EMAC.h" +#include "netsocket/L3IP.h" #include "netsocket/OnboardNetworkStack.h" #include "LWIPMemoryManager.h" @@ -122,7 +123,7 @@ public: #if LWIP_ETHERNET static err_t emac_low_level_output(struct netif *netif, struct pbuf *p); - void emac_input(emac_mem_buf_t *buf); + void emac_input(net_stack_mem_buf_t *buf); void emac_state_change(bool up); #if LWIP_IGMP static err_t emac_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action); @@ -134,10 +135,28 @@ public: static err_t emac_if_init(struct netif *netif); #endif +#if LWIP_L3IP + static err_t l3ip_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr); + void l3ip_input(net_stack_mem_buf_t *buf); + void l3ip_state_change(bool up); +#if LWIP_IGMP + static err_t l3ip_multicast_ipv4_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action); +#endif +#if LWIP_IPV6_MLD + static err_t l3ip_multicast_ipv6_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action); +#endif + + static err_t l3ip_if_init(struct netif *netif); +#endif + union { #if LWIP_ETHERNET EMAC *emac; /**< HW specific emac implementation */ #endif +#if LWIP_L3IP + L3IP *l3ip; /**< L3IP implementation */ +#endif + void *hw; /**< alternative implementation pointer - used for PPP */ }; @@ -183,6 +202,18 @@ public: */ virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out); + /** Register a network interface with the IP stack + * + * Connects L3IP layer with the IP stack and initializes all the required infrastructure. + * This function should be called only once for each available interface. + * + * @param l3ip L3IP HAL implementation for this network interface + * @param default_if true if the interface should be treated as the default one + * @param[out] interface_out pointer to stack interface object controlling the L3IP + * @return NSAPI_ERROR_OK on success, or error code + */ + virtual nsapi_error_t add_l3ip_interface(L3IP &l3ip, bool default_if, OnboardNetworkStack::Interface **interface_out); + /** Register a PPP interface with the IP stack * * Connects PPP layer with the IP stack and initializes all the required infrastructure. @@ -202,6 +233,17 @@ public: */ nsapi_error_t _add_ppp_interface(void *pcb, bool default_if, nsapi_ip_stack_t stack, LWIP::Interface **interface_out); + /** Remove a network interface from IP stack + * + * Connects L3IP layer with the IP stack and initializes all the required infrastructure. + * This function should be called only once for each available interface. + + + * @param[out] interface_out pointer to stack interface object controlling the L3IP + * @return NSAPI_ERROR_OK on success, or error code + */ + virtual nsapi_error_t remove_l3ip_interface(OnboardNetworkStack::Interface **interface_out); + /** Get a domain name server from a list of servers to query * * Returns a DNS server address for a index. If returns error no more diff --git a/features/lwipstack/lwipopts.h b/features/lwipstack/lwipopts.h index 073a060242..3a3ce6c85e 100644 --- a/features/lwipstack/lwipopts.h +++ b/features/lwipstack/lwipopts.h @@ -331,6 +331,7 @@ #define LWIP_ETHERNET 0 #endif // MBED_CONF_LWIP_ETHERNET_ENABLED +#define LWIP_L3IP 0 // Note generic macro name used rather than MBED_CONF_LWIP_PPP_ENABLED // to allow users like PPPCellularInterface to detect that nsapi_ppp.h is available. #if NSAPI_PPP_AVAILABLE diff --git a/features/netsocket/EMACMemoryManager.h b/features/netsocket/EMACMemoryManager.h index ad97d6675c..e69f24bea6 100644 --- a/features/netsocket/EMACMemoryManager.h +++ b/features/netsocket/EMACMemoryManager.h @@ -37,150 +37,12 @@ */ #include "nsapi.h" +#include "NetStackMemoryManager.h" typedef void emac_mem_buf_t; // Memory buffer -class EMACMemoryManager { -public: +class EMACMemoryManager : public NetStackMemoryManager { - /** - * Allocates memory buffer from the heap - * - * Memory buffer allocated from heap is always contiguous and can be arbitrary size. - * - * @param size Size of the memory to allocate in bytes - * @param align Memory alignment requirement in bytes - * @return Allocated memory buffer, or NULL in case of error - */ - virtual emac_mem_buf_t *alloc_heap(uint32_t size, uint32_t align) = 0; - - /** - * Allocates memory buffer chain from a pool - * - * Memory allocated from pool is contiguous if size is equal or less than - * (aligned) allocation unit, otherwise may be chained. Will typically come from - * fixed-size packet pool memory. - * - * @param size Total size of the memory to allocate in bytes - * @param align Memory alignment requirement for each buffer in bytes - * @return Allocated memory buffer chain, or NULL in case of error - */ - virtual emac_mem_buf_t *alloc_pool(uint32_t size, uint32_t align) = 0; - - /** - * Get memory buffer pool allocation unit - * - * Returns the maximum size of contiguous memory that can be allocated from a pool. - * - * @param align Memory alignment requirement in bytes - * @return Contiguous memory size - */ - virtual uint32_t get_pool_alloc_unit(uint32_t align) const = 0; - - /** - * Free memory buffer chain - * - * If memory buffer is chained must point to the start of the chain. Frees all buffers - * from the chained list. - * - * @param buf Memory buffer chain to be freed. - */ - virtual void free(emac_mem_buf_t *buf) = 0; - - /** - * Return total length of a memory buffer chain - * - * Returns a total length of this buffer and any following buffers in the chain. - * - * @param buf Memory buffer chain - * @return Total length in bytes - */ - virtual uint32_t get_total_len(const emac_mem_buf_t *buf) const = 0; - - /** - * Copy a memory buffer chain - * - * Copies data from one buffer chain to another. Copy operation does not adjust the lengths - * of the copied-to memory buffer chain, so chain total lengths must be the same. - * - * @param to_buf Memory buffer chain to copy to - * @param from_buf Memory buffer chain to copy from - */ - virtual void copy(emac_mem_buf_t *to_buf, const emac_mem_buf_t *from_buf) = 0; - - /** - * Copy to a memory buffer chain - * - * Copies data to a buffer chain. Copy operation does not adjust the lengths - * of the copied-to memory buffer chain, so chain total length must match the - * copied length. - * - * @param to_buf Memory buffer chain to copy to - * @param ptr Pointer to data - * @param len Data length - */ - virtual void copy_to_buf(emac_mem_buf_t *to_buf, const void *ptr, uint32_t len); - - /** - * Copy from a memory buffer chain - * - * Copies data from a memory buffer chain. - * - * @param len Data length - * @param ptr Pointer to data - * @param from_buf Memory buffer chain to copy from - * @return Length of the data that was copied - */ - virtual uint32_t copy_from_buf(void *ptr, uint32_t len, const emac_mem_buf_t *from_buf) const; - - /** - * Concatenate two memory buffer chains - * - * Concatenates buffer chain to end of the other buffer chain. Concatenated-to buffer total length - * is adjusted accordingly. cat_buf must point to the start of a the chain. After concatenation - * to_buf's chain now owns those buffers, and they will be freed when the to_buf chain is freed. - * - * @param to_buf Memory buffer chain to concatenate to - * @param cat_buf Memory buffer chain to concatenate - */ - virtual void cat(emac_mem_buf_t *to_buf, emac_mem_buf_t *cat_buf) = 0; - - /** - * Returns the next buffer - * - * Returns the next buffer from the memory buffer chain. - * - * @param buf Memory buffer - * @return The next memory buffer, or NULL if last - */ - virtual emac_mem_buf_t *get_next(const emac_mem_buf_t *buf) const = 0; - - /** - * Return pointer to the payload of the buffer - * - * @param buf Memory buffer - * @return Pointer to the payload - */ - virtual void *get_ptr(const emac_mem_buf_t *buf) const = 0; - - /** - * Return payload size of the buffer - * - * @param buf Memory buffer - * @return Size in bytes - */ - virtual uint32_t get_len(const emac_mem_buf_t *buf) const = 0; - - /** - * Sets the payload size of the buffer - * - * The allocated payload size will not change. It is not permitted - * to change the length of a buffer that is not the first (or only) in a chain. - * - * @param buf Memory buffer - * @param len Payload size, must be less or equal allocated size - */ - virtual void set_len(emac_mem_buf_t *buf, uint32_t len) = 0; }; #endif /* EMAC_MEMORY_MANAGER_H */ diff --git a/features/netsocket/L3IP.h b/features/netsocket/L3IP.h new file mode 100644 index 0000000000..e89b183b01 --- /dev/null +++ b/features/netsocket/L3IP.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef L3IP_H +#define L3IP_H + +#include +#include "Callback.h" +#include "NetStackMemoryManager.h" + + +/** + * This interface should be used to abstract low level access to networking hardware + * All operations receive a `void *` hardware pointer which an l3ip device provides when + * it is registered with a stack. + */ +class L3IP { +public: + + /** Return the default on-board L3IP + * + * Returns the default on-board L3IP - this will be target-specific, and + * may not be available on all targets. + */ + static L3IP &get_default_instance(); + + /** + * Callback to be registered with L3IP interface and to be called for received packets + * + * @param buf Received data + */ + //typedef void (*l3ip_link_input_fn)(void *data, net_stack_mem_buf_t *buf); + typedef mbed::Callback l3ip_link_input_cb_t; + + /** + * Callback to be registered with L3IP interface and to be called for link status changes + * + * @param up Link status + */ + //typedef void (*l3ip_link_state_change_fn)(void *data, bool up); + typedef mbed::Callback l3ip_link_state_change_cb_t; + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const = 0; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the l3ip device. + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const = 0; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of characters to copy + */ + virtual void get_ifname(char *name, uint8_t size) const = 0; + + /** + * Sends the packet over the link + * + * That cannot be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, false otherwise + */ + virtual bool link_out(net_stack_mem_buf_t *buf) = 0; + + /** + * Initializes the hardware + * + * @return True on success, False in case of an error. + */ + virtual bool power_up() = 0; + + /** + * Deinitializes the hardware + * + */ + virtual void power_down() = 0; + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(l3ip_link_input_cb_t input_cb) = 0; + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(l3ip_link_state_change_cb_t state_cb) = 0; + + /** Add device to an IP4 multicast group + * + * @param address An IP4 multicast group address + */ + virtual void add_ipv4_multicast_group(const char *address) = 0; + + /** Add device to an IP6 multicast group + * + * @param address An IP6 multicast group address + */ + virtual void add_ipv6_multicast_group(const char *address) = 0; + + /** Remove device from an IPV4 multicast group + * + * @param address An IPV4 multicast group address + */ + virtual void remove_ipv4_multicast_group(const char *address) = 0; + + /** Remove device from an IPV6 multicast group + * + * @param address An IPV6 multicast group address + */ + virtual void remove_ipv6_multicast_group(const char *address) = 0; + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all) = 0; + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(NetStackMemoryManager &mem_mngr) = 0; +}; + + + + +#endif /* L3IP_H */ diff --git a/features/netsocket/L3IPInterface.cpp b/features/netsocket/L3IPInterface.cpp new file mode 100644 index 0000000000..27a82af95a --- /dev/null +++ b/features/netsocket/L3IPInterface.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "L3IPInterface.h" +using namespace mbed; + +/* Interface implementation */ +L3IPInterface::L3IPInterface(L3IP &l3ip, OnboardNetworkStack &stack) : + _l3ip(l3ip), + _stack(stack), + _interface(NULL), + _dhcp(true), + _blocking(true), + _ip_address(), + _netmask(), + _gateway() +{ +} + +L3IPInterface::~ L3IPInterface() +{ + _stack.remove_l3ip_interface(&_interface); +} + +nsapi_error_t L3IPInterface::set_network(const char *ip_address, const char *netmask, const char *gateway) +{ + _dhcp = false; + + strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address)); + _ip_address[sizeof(_ip_address) - 1] = '\0'; + strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask)); + _netmask[sizeof(_netmask) - 1] = '\0'; + strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway)); + _gateway[sizeof(_gateway) - 1] = '\0'; + + return NSAPI_ERROR_OK; +} + +nsapi_error_t L3IPInterface::set_dhcp(bool dhcp) +{ + _dhcp = dhcp; + return NSAPI_ERROR_OK; +} + +nsapi_error_t L3IPInterface::connect() +{ + if (!_interface) { + nsapi_error_t err = _stack.add_l3ip_interface(_l3ip, true, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + } + + return _interface->bringup(_dhcp, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + DEFAULT_STACK, + _blocking); +} + +nsapi_error_t L3IPInterface::disconnect() +{ + if (_interface) { + return _interface->bringdown(); + } + return NSAPI_ERROR_NO_CONNECTION; +} + +const char *L3IPInterface::get_ip_address() +{ + if (_interface && _interface->get_ip_address(_ip_address, sizeof(_ip_address))) { + return _ip_address; + } + + return NULL; +} + +const char *L3IPInterface::get_netmask() +{ + if (_interface && _interface->get_netmask(_netmask, sizeof(_netmask))) { + return _netmask; + } + + return 0; +} + +const char *L3IPInterface::get_gateway() +{ + if (_interface && _interface->get_gateway(_gateway, sizeof(_gateway))) { + return _gateway; + } + + return 0; +} + +NetworkStack *L3IPInterface::get_stack() +{ + return &_stack; +} + +void L3IPInterface::attach( + mbed::Callback status_cb) +{ + _connection_status_cb = status_cb; + if (_interface) { + _interface->attach(status_cb); + } +} + +nsapi_connection_status_t L3IPInterface::get_connection_status() const +{ + if (_interface) { + return _interface->get_connection_status(); + } else { + return NSAPI_STATUS_DISCONNECTED; + } +} + +nsapi_error_t L3IPInterface::set_blocking(bool blocking) +{ + _blocking = blocking; + return NSAPI_ERROR_OK; +} diff --git a/features/netsocket/L3IPInterface.h b/features/netsocket/L3IPInterface.h new file mode 100644 index 0000000000..926373ccef --- /dev/null +++ b/features/netsocket/L3IPInterface.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef L3IP_INTERFACE_H +#define L3IP_INTERFACE_H + +#include "nsapi.h" +#include "L3IP.h" +#include "OnboardNetworkStack.h" + + +/** L3IPInterface class + * Implementation of the NetworkInterface for an IP-based driver + * + * This class provides the necessary glue logic to create a NetworkInterface + * based on an L3IP and an OnboardNetworkStack. Cellular Interface drivers derive from it. + * + * Drivers derived from L3IPInterface should be constructed so that their + * L3IP is functional without the need to call `connect()`. + */ +class L3IPInterface : public virtual NetworkInterface { +public: + /** Create an L3IP-based network interface. + * + * The default arguments obtain the default L3IP, which will be target- + * dependent (and the target may have some JSON option to choose which + * is the default, if there are multiple). The default stack is configured + * by JSON option nsapi.default-stack. + * + * Due to inability to return errors from the constructor, no real + * work is done until the first call to connect(). + * + * @param l3ip Reference to L3IP to use + * @param stack Reference to onboard-network stack to use + */ + L3IPInterface(L3IP &l3ip = L3IP::get_default_instance(), + OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()); + ~L3IPInterface(); + /** Set a static IP address + * + * Configures this network interface to use a static IP address. + * Implicitly disables DHCP, which can be enabled in set_dhcp. + * Requires that the network is disconnected. + * + * @param ip_address Null-terminated representation of the local IP address + * @param netmask Null-terminated representation of the local network mask + * @param gateway Null-terminated representation of the local gateway + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t set_network(const char *ip_address, const char *netmask, const char *gateway); + + /** Enable or disable DHCP on the network + * + * Requires that the network is disconnected + * + * @param dhcp False to disable dhcp (defaults to enabled) + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t set_dhcp(bool dhcp); + + /** Start the interface + * @return 0 on success, negative on failure + */ + virtual nsapi_error_t connect(); + + /** Stop the interface + * @return 0 on success, negative on failure + */ + virtual nsapi_error_t disconnect(); + + /** Get the local IP address + * + * @return Null-terminated representation of the local IP address + * or null if no IP address has been recieved + */ + virtual const char *get_ip_address(); + + /** Get the local network mask + * + * @return Null-terminated representation of the local network mask + * or null if no network mask has been recieved + */ + virtual const char *get_netmask(); + + /** Get the local gateways + * + * @return Null-terminated representation of the local gateway + * or null if no network mask has been recieved + */ + virtual const char *get_gateway(); + + /** Register callback for status reporting + * + * @param status_cb The callback for status changes + */ + virtual void attach(mbed::Callback status_cb); + + /** Get the connection status + * + * @return The connection status according to nsapi_connection_status_t + */ + virtual nsapi_connection_status_t get_connection_status() const; + + /** Set blocking status of connect() which by default should be blocking + * + * @param blocking true if connect is blocking + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t set_blocking(bool blocking); + + /** Provide access to the L3IP + * + * This should be used with care - normally the network stack would + * control the L3IP, so manipulating the L3IP while the stack + * is also using it (ie after connect) will likely cause problems. + * + * @return Reference to the L3IP in use + */ + L3IP &getl3ip() const + { + return _l3ip; + } + + virtual L3IPInterface *l3ipInterface() + { + return this; + } + +protected: + /** Provide access to the underlying stack + * + * @return The underlying network stack + */ + virtual NetworkStack *get_stack(); + + L3IP &_l3ip; + OnboardNetworkStack &_stack; + OnboardNetworkStack::Interface *_interface; + bool _dhcp; + bool _blocking; + char _ip_address[NSAPI_IPv6_SIZE]; + char _netmask[NSAPI_IPv4_SIZE]; + char _gateway[NSAPI_IPv4_SIZE]; + mbed::Callback _connection_status_cb; +}; + +#endif diff --git a/features/netsocket/EMACMemoryManager.cpp b/features/netsocket/NetStackMemoryManager.cpp similarity index 82% rename from features/netsocket/EMACMemoryManager.cpp rename to features/netsocket/NetStackMemoryManager.cpp index 1e6c5da20f..86d643d590 100644 --- a/features/netsocket/EMACMemoryManager.cpp +++ b/features/netsocket/NetStackMemoryManager.cpp @@ -1,4 +1,6 @@ -/* Copyright (c) 2018 ARM Limited +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +15,9 @@ * limitations under the License. */ -#include "EMACMemoryManager.h" +#include "NetStackMemoryManager.h" -void EMACMemoryManager::copy_to_buf(emac_mem_buf_t *to_buf, const void *ptr, uint32_t len) +void NetStackMemoryManager::copy_to_buf(net_stack_mem_buf_t *to_buf, const void *ptr, uint32_t len) { while (to_buf && len) { void *copy_to_ptr = get_ptr(to_buf); @@ -35,7 +37,7 @@ void EMACMemoryManager::copy_to_buf(emac_mem_buf_t *to_buf, const void *ptr, uin } } -uint32_t EMACMemoryManager::copy_from_buf(void *ptr, uint32_t len, const emac_mem_buf_t *from_buf) const +uint32_t NetStackMemoryManager::copy_from_buf(void *ptr, uint32_t len, const net_stack_mem_buf_t *from_buf) const { uint32_t copied_len = 0; diff --git a/features/netsocket/NetStackMemoryManager.h b/features/netsocket/NetStackMemoryManager.h new file mode 100644 index 0000000000..91162a9a83 --- /dev/null +++ b/features/netsocket/NetStackMemoryManager.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NET_STACK_MEMORY_MANAGER_H +#define NET_STACK_MEMORY_MANAGER_H + +/** + * Network Stack interface memory manager + * + * This interface provides abstraction for memory modules used in different IP stacks (often to accommodate zero + * copy). NetStack interface is required to accept output packets and provide received data using this stack- + * independent API. This header should be implemented for each IP stack, so that we keep EMAC module independent. + * + * NetStack memory interface uses memory buffer chains to store data. Data passed in either direction + * may be either contiguous (a single-buffer chain), or may consist of multiple buffers. + * Chaining of the buffers is made using singly-linked list. The NetStack data-passing APIs do not specify + * alignment or structure of the chain in either direction. + * + * Memory buffers can be allocated either from heap or from memory pools. Heap buffers are always contiguous. + * Memory pool buffers may be either contiguous or chained depending on allocation size. + * + * On NetStack interface buffer chain ownership is transferred. EMAC must free buffer chain that it is given for + * link output and the stack must free the buffer chain that it is given for link input. + * + */ + +#include "nsapi.h" + +typedef void net_stack_mem_buf_t; // Memory buffer + +class NetStackMemoryManager { +public: + + /** + * Allocates memory buffer from the heap + * + * Memory buffer allocated from heap is always contiguous and can be arbitrary size. + * + * @param size Size of the memory to allocate in bytes + * @param align Memory alignment requirement in bytes + * @return Allocated memory buffer, or NULL in case of error + */ + virtual net_stack_mem_buf_t *alloc_heap(uint32_t size, uint32_t align) = 0; + + /** + * Allocates memory buffer chain from a pool + * + * Memory allocated from pool is contiguous if size is equal or less than + * (aligned) allocation unit, otherwise may be chained. Will typically come from + * fixed-size packet pool memory. + * + * @param size Total size of the memory to allocate in bytes + * @param align Memory alignment requirement for each buffer in bytes + * @return Allocated memory buffer chain, or NULL in case of error + */ + virtual net_stack_mem_buf_t *alloc_pool(uint32_t size, uint32_t align) = 0; + + /** + * Get memory buffer pool allocation unit + * + * Returns the maximum size of contiguous memory that can be allocated from a pool. + * + * @param align Memory alignment requirement in bytes + * @return Contiguous memory size + */ + virtual uint32_t get_pool_alloc_unit(uint32_t align) const = 0; + + /** + * Free memory buffer chain + * + * Frees all buffers from the chained list. + * + * @param buf Memory buffer chain to be freed. + */ + virtual void free(net_stack_mem_buf_t *buf) = 0; + + /** + * Return total length of a memory buffer chain + * + * Returns a total length of this buffer and any following buffers in the chain. + * + * @param buf Memory buffer chain + * @return Total length in bytes + */ + virtual uint32_t get_total_len(const net_stack_mem_buf_t *buf) const = 0; + + /** + * Copy a memory buffer chain + * + * Copies data from one buffer chain to another. Copy operation does not adjust the lengths + * of the copied-to memory buffer chain, so chain total lengths must be the same. + * + * @param to_buf Memory buffer chain to copy to + * @param from_buf Memory buffer chain to copy from + */ + virtual void copy(net_stack_mem_buf_t *to_buf, const net_stack_mem_buf_t *from_buf) = 0; + + /** + * Copy to a memory buffer chain + * + * Copies data to a buffer chain. Copy operation does not adjust the lengths + * of the copied-to memory buffer chain, so chain total length must match the + * copied length. + * + * @param to_buf Memory buffer chain to copy to + * @param ptr Pointer to data + * @param len Data length + */ + virtual void copy_to_buf(net_stack_mem_buf_t *to_buf, const void *ptr, uint32_t len); + + /** + * Copy from a memory buffer chain + * + * Copies data from a memory buffer chain. + * + * @param len Data length + * @param ptr Pointer to data + * @param from_buf Memory buffer chain to copy from + * @return Length of the data that was copied + */ + virtual uint32_t copy_from_buf(void *ptr, uint32_t len, const net_stack_mem_buf_t *from_buf) const; + + /** + * Concatenate two memory buffer chains + * + * Concatenates buffer chain to end of the other buffer chain. Concatenated-to buffer total length + * is adjusted accordingly. cat_buf must point to the start of a the chain. After concatenation + * to_buf's chain now owns those buffers, and they will be freed when the to_buf chain is freed. + * + * @param to_buf Memory buffer chain to concatenate to + * @param cat_buf Memory buffer chain to concatenate + */ + virtual void cat(net_stack_mem_buf_t *to_buf, net_stack_mem_buf_t *cat_buf) = 0; + + /** + * Returns the next buffer + * + * Returns the next buffer from the memory buffer chain. + * + * @param buf Memory buffer + * @return The next memory buffer, or NULL if last + */ + virtual net_stack_mem_buf_t *get_next(const net_stack_mem_buf_t *buf) const = 0; + + /** + * Return pointer to the payload of the buffer + * + * @param buf Memory buffer + * @return Pointer to the payload + */ + virtual void *get_ptr(const net_stack_mem_buf_t *buf) const = 0; + + /** + * Return payload size of the buffer + * + * @param buf Memory buffer + * @return Size in bytes + */ + virtual uint32_t get_len(const net_stack_mem_buf_t *buf) const = 0; + + /** + * Sets the payload size of the buffer + * + * The allocated payload size will not change. It is not permitted + * to change the length of a buffer that is not the first (or only) in a chain. + * + * @param buf Memory buffer + * @param len Payload size, must be less or equal to the allocated size + */ + virtual void set_len(net_stack_mem_buf_t *buf, uint32_t len) = 0; +}; + +#endif /* NET_STACK_MEMORY_MANAGER_H */ diff --git a/features/netsocket/OnboardNetworkStack.h b/features/netsocket/OnboardNetworkStack.h index 35ca37b08b..650b2cd4fa 100644 --- a/features/netsocket/OnboardNetworkStack.h +++ b/features/netsocket/OnboardNetworkStack.h @@ -21,6 +21,7 @@ #include "NetworkStack.h" #include "EMAC.h" +#include "L3IP.h" /** * mbed OS API for onboard IP stack abstraction @@ -133,6 +134,16 @@ public: * @return NSAPI_ERROR_OK on success, or error code */ virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out) = 0; + + virtual nsapi_error_t add_l3ip_interface(L3IP &l3ip, bool default_if, Interface **interface_out) + { + return NSAPI_ERROR_OK; + }; + + virtual nsapi_error_t remove_l3ip_interface(Interface **interface_out) + { + return NSAPI_ERROR_OK; + }; }; #endif /* MBED_IPSTACK_H */ diff --git a/features/netsocket/cellular/cellular_driver_l3ip.cpp b/features/netsocket/cellular/cellular_driver_l3ip.cpp new file mode 100644 index 0000000000..0eaef3999d --- /dev/null +++ b/features/netsocket/cellular/cellular_driver_l3ip.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "mbed_interface.h" +#include "netsocket/nsapi_types.h" +#include "cellular_driver_l3ip.h" + +Cellular_driver_L3IP::Cellular_driver_L3IP() +{ +} + + +bool Cellular_driver_L3IP::link_out(net_stack_mem_buf_t *buf) +{ + + return true; +} + + +bool Cellular_driver_L3IP::power_up() +{ + + return true; +} + +uint32_t Cellular_driver_L3IP::get_mtu_size() const +{ + return 0; +} + +uint32_t Cellular_driver_L3IP::get_align_preference() const +{ + return 0; +} + +void Cellular_driver_L3IP::get_ifname(char *name, uint8_t size) const +{ + +} + + + +void Cellular_driver_L3IP::set_link_input_cb(l3ip_link_input_cb_t input_cb) +{ + l3ip_link_input_cb = input_cb; +} + +void Cellular_driver_L3IP::set_link_state_cb(l3ip_link_state_change_cb_t state_cb) +{ + l3ip_link_state_cb = state_cb; +} + +void Cellular_driver_L3IP::add_ipv4_multicast_group(const char *address) +{ + +} + +void Cellular_driver_L3IP::add_ipv6_multicast_group(const char *address) +{ + +} + +void Cellular_driver_L3IP::remove_ipv4_multicast_group(const char *address) +{ + +} + +void Cellular_driver_L3IP::remove_ipv6_multicast_group(const char *address) +{ + +} + +void Cellular_driver_L3IP::set_all_multicast(bool all) +{ + +} + +void Cellular_driver_L3IP::power_down() +{ + +} + +void Cellular_driver_L3IP::set_memory_manager(NetStackMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + + +Cellular_driver_L3IP &Cellular_driver_L3IP::get_instance() +{ + static Cellular_driver_L3IP l3ip_test_driver; + return l3ip_test_driver; +} + +// Weak so a module can override +MBED_WEAK L3IP &L3IP::get_default_instance() +{ + return Cellular_driver_L3IP::get_instance(); +} + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ + diff --git a/features/netsocket/cellular/cellular_driver_l3ip.h b/features/netsocket/cellular/cellular_driver_l3ip.h new file mode 100644 index 0000000000..da3cd77d4a --- /dev/null +++ b/features/netsocket/cellular/cellular_driver_l3ip.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CELLULAR_DRIVER_L3IP_H_ +#define CELLULAR_DRIVER_L3IP_H_ + +#include "L3IP.h" + + +class Cellular_driver_L3IP : public L3IP { +public: + Cellular_driver_L3IP(); + + static Cellular_driver_L3IP &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the cellular device. + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of characters to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Sends the packet over the link + * + * That cannot be called from an interrupt context. + * + * @param buf Packet to be sent + * @return True if the packet was sent, false otherwise + */ + virtual bool link_out(net_stack_mem_buf_t *buf); + + /** + * Initializes the hardware + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the hardware + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(l3ip_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(l3ip_link_state_change_cb_t state_cb); + + /** Add device to an IP4 multicast group + * + * @param address an IP4 multicast group address + */ + virtual void add_ipv4_multicast_group(const char *address); + + /** Add device to an IP6 multicast group + * + * @param address an IP6 multicast group address + */ + virtual void add_ipv6_multicast_group(const char *address); + + /** Remove device from an IPV4 multicast group + * + * @param address An IPV4 multicast group address + */ + virtual void remove_ipv4_multicast_group(const char *address); + + /** Remove device from an IPV6 multicast group + * + * @param address An IPV6 multicast group address + */ + virtual void remove_ipv6_multicast_group(const char *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(NetStackMemoryManager &mem_mngr); + +private: + + l3ip_link_input_cb_t l3ip_link_input_cb; /**< Callback for incoming data */ + l3ip_link_state_change_cb_t l3ip_link_state_cb; /**< Link state change callback */ + NetStackMemoryManager *memory_manager; /**< Memory manager */ + +}; + +#endif /* CELLULAR_DRIVER_L3IP_H_ */ diff --git a/features/netsocket/nsapi_types.h b/features/netsocket/nsapi_types.h index c819c471a8..21f91d01dc 100644 --- a/features/netsocket/nsapi_types.h +++ b/features/netsocket/nsapi_types.h @@ -127,6 +127,10 @@ typedef enum nsapi_security { NSAPI_SECURITY_UNKNOWN = 0xFF, /*!< unknown/unsupported security in scan results */ } nsapi_security_t; +/** Maximum size of network interface name + */ +#define NSAPI_INTERFACE_NAME_SIZE 2 + /** Maximum size of IP address representation */ #define NSAPI_IP_SIZE NSAPI_IPv6_SIZE