diff --git a/features/FEATURE_LWIP/lwip-interface/LWIPInterface.cpp b/features/FEATURE_LWIP/lwip-interface/LWIPInterface.cpp index 91e44db6f0..e4e18be74a 100644 --- a/features/FEATURE_LWIP/lwip-interface/LWIPInterface.cpp +++ b/features/FEATURE_LWIP/lwip-interface/LWIPInterface.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "lwip/opt.h" #include "lwip/api.h" @@ -335,6 +336,7 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN return NSAPI_ERROR_NO_MEMORY; } interface->emac = &emac; + interface->memory_manager = &memory_manager; interface->ppp = false; #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) @@ -481,7 +483,6 @@ nsapi_error_t LWIP::Interface::bringup(bool dhcp, const char *ip, const char *ne client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING); } - netif_set_up(&netif); if (ppp) { err_t err = ppp_lwip_connect(hw); if (err) { diff --git a/features/FEATURE_LWIP/lwip-interface/LWIPInterfaceEMAC.cpp b/features/FEATURE_LWIP/lwip-interface/LWIPInterfaceEMAC.cpp index f7fb2866a4..fde9a1b389 100644 --- a/features/FEATURE_LWIP/lwip-interface/LWIPInterfaceEMAC.cpp +++ b/features/FEATURE_LWIP/lwip-interface/LWIPInterfaceEMAC.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ -#include "emac_stack_mem.h" #include "lwip/tcpip.h" #include "lwip/tcp.h" #include "lwip/ip.h" @@ -29,12 +28,16 @@ err_t LWIP::Interface::emac_low_level_output(struct netif *netif, struct pbuf *p) { + /* 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->emac->link_out(p); return ret ? ERR_OK : ERR_IF; } -void LWIP::Interface::emac_input(emac_stack_mem_t *buf) +void LWIP::Interface::emac_input(emac_mem_buf_t *buf) { struct pbuf *p = static_cast(buf); @@ -136,6 +139,7 @@ err_t LWIP::Interface::emac_if_init(struct netif *netif) int err = ERR_OK; LWIP::Interface *mbed_if = static_cast(netif->state); + mbed_if->emac->set_memory_manager(*mbed_if->memory_manager); mbed_if->emac->set_link_input_cb(mbed::callback(mbed_if, &LWIP::Interface::emac_input)); mbed_if->emac->set_link_state_cb(mbed::callback(mbed_if, &LWIP::Interface::emac_state_change)); diff --git a/features/FEATURE_LWIP/lwip-interface/LWIPMemoryManager.cpp b/features/FEATURE_LWIP/lwip-interface/LWIPMemoryManager.cpp new file mode 100644 index 0000000000..a97a576692 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/LWIPMemoryManager.cpp @@ -0,0 +1,153 @@ +/* Copyright (c) 2017 ARM Limited + * + * 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 "pbuf.h" +#include "LWIPMemoryManager.h" + +emac_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) { + return NULL; + } + + align_memory(pbuf, align); + + return static_cast(pbuf); +} + +emac_mem_buf_t *LWIPMemoryManager::alloc_pool(uint32_t size, uint32_t align) +{ + uint32_t total_align = count_total_align(size, align); + + struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, size + total_align, PBUF_POOL); + if (pbuf == NULL) { + return NULL; + } + + align_memory(pbuf, align); + + return static_cast(pbuf); +} + +uint32_t LWIPMemoryManager::get_pool_alloc_unit(uint32_t align) const +{ + uint32_t alloc_unit = LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - align; + return alloc_unit; +} + +void LWIPMemoryManager::free(emac_mem_buf_t *buf) +{ + pbuf_free(static_cast(buf)); +} + +uint32_t LWIPMemoryManager::get_total_len(const emac_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) +{ + pbuf_copy(static_cast(to_buf), static_cast(from_buf)); +} + +void LWIPMemoryManager::cat(emac_mem_buf_t *to_buf, emac_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 +{ + if (!buf) { + return NULL; + } + struct pbuf *next = (static_cast(buf))->next; + return static_cast(next); +} + +void *LWIPMemoryManager::get_ptr(const emac_mem_buf_t *buf) const +{ + return (static_cast(buf))->payload; +} + +uint32_t LWIPMemoryManager::get_len(const emac_mem_buf_t *buf) const +{ + return (static_cast(buf))->len; +} + +void LWIPMemoryManager::set_len(emac_mem_buf_t *buf, uint32_t len) +{ + struct pbuf *pbuf = static_cast(buf); + pbuf->len = len; + set_total_len(pbuf); +} + +uint32_t LWIPMemoryManager::count_total_align(uint32_t size, uint32_t align) +{ + uint32_t buffers = size / get_pool_alloc_unit(align); + if (size % get_pool_alloc_unit(align) != 0) { + buffers++; + } + return buffers * align; +} + +void LWIPMemoryManager::align_memory(struct pbuf *pbuf, uint32_t align) +{ + if (!align) { + return; + } + + struct pbuf *pbuf_start = pbuf; + + while (pbuf) { + uint32_t remainder = reinterpret_cast(pbuf->payload) % align; + if (remainder) { + uint32_t offset = align - remainder; + if (offset >= align) { + offset = align; + } + pbuf->payload = static_cast(pbuf->payload) + offset; + } + pbuf->len -= align; + pbuf = pbuf->next; + } + + // Correct total lengths + set_total_len(pbuf_start); +} + +void LWIPMemoryManager::set_total_len(struct pbuf *pbuf) +{ + if (!pbuf->next) { + pbuf->tot_len = pbuf->len; + return; + } + + uint32_t total_len; + struct pbuf *pbuf_tailing; + + while (pbuf) { + total_len = pbuf->len; + + pbuf_tailing = pbuf->next; + while (pbuf_tailing) { + total_len += pbuf_tailing->len; + pbuf_tailing = pbuf_tailing->next; + } + + pbuf->tot_len = total_len; + pbuf = pbuf->next; + } +} diff --git a/features/FEATURE_LWIP/lwip-interface/LWIPMemoryManager.h b/features/FEATURE_LWIP/lwip-interface/LWIPMemoryManager.h new file mode 100644 index 0000000000..7a7d8e3a39 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/LWIPMemoryManager.h @@ -0,0 +1,175 @@ +/* Copyright (c) 2017 ARM Limited + * + * 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 LWIP_MEMORY_MANAGER_H +#define LWIP_MEMORY_MANAGER_H + +#include "EMACMemoryManager.h" + +class LWIPMemoryManager : public EMACMemoryManager { +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 emac_mem_buf_t *alloc_heap(uint32_t size, uint32_t align); + + /** + * 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); + + /** + * 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; + + /** + * 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); + + /** + * 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; + + /** + * 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); + + /** + * 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); + + /** + * 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; + + /** + * 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; + + /** + * 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; + + /** + * 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); + +private: + + /** + * Returns a total memory alignment size + * + * Calculates the total memory alignment size for a memory buffer chain. + * Used internally on pool allocation. + * + * @param size Size of the memory to allocate in bytes + * @param align Memory alignment requirement for each buffer in bytes + * @return Total alignment needed in bytes + */ + uint32_t count_total_align(uint32_t size, uint32_t align); + + /** + * Aligns a memory buffer chain + * + * Aligns a memory buffer chain and updates lengths and total lengths + * accordingly. There needs to be enough overhead to do the alignment + * for all buffers. + * + * @param pbuf Memory buffer + * @param align Memory alignment requirement for each buffer in bytes + */ + void align_memory(struct pbuf *pbuf, uint32_t align); + + /** + * Sets total lengths of a memory buffer chain + * + * Sets total length fields for a memory buffer chain based on buffer + * length fields. All total lengths are calculated again. + * + * @param pbuf Memory buffer + */ + void set_total_len(struct pbuf *pbuf); +}; + +#endif /* LWIP_MEMORY_MANAGER_H */ diff --git a/features/FEATURE_LWIP/lwip-interface/LWIPStack.h b/features/FEATURE_LWIP/lwip-interface/LWIPStack.h index 7adc9ddcb0..706474f3a3 100644 --- a/features/FEATURE_LWIP/lwip-interface/LWIPStack.h +++ b/features/FEATURE_LWIP/lwip-interface/LWIPStack.h @@ -17,7 +17,6 @@ #ifndef LWIPSTACK_H_ #define LWIPSTACK_H_ -#include "emac_stack_mem.h" #include "lwip/tcpip.h" #include "lwip/tcp.h" #include "lwip/ip.h" @@ -27,6 +26,7 @@ #include "netsocket/nsapi_types.h" #include "netsocket/EMAC.h" #include "netsocket/OnboardNetworkStack.h" +#include "LWIPMemoryManager.h" class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { @@ -119,8 +119,9 @@ public: static void netif_link_irq(struct netif *netif); static void netif_status_irq(struct netif *netif); + #if LWIP_ETHERNET static err_t emac_low_level_output(struct netif *netif, struct pbuf *p); - void emac_input(emac_stack_mem_t *buf); + void emac_input(emac_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); @@ -130,9 +131,12 @@ public: #endif static err_t emac_if_init(struct netif *netif); + #endif union { + #if LWIP_ETHERNET EMAC *emac; /**< HW specific emac implementation */ + #endif void *hw; /**< alternative implementation pointer - used for PPP */ }; @@ -161,6 +165,7 @@ public: bool ppp; mbed::Callback client_callback; struct netif netif; + LWIPMemoryManager *memory_manager; }; /** Register a network interface with the IP stack @@ -417,6 +422,7 @@ protected: virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen); private: + struct mbed_lwip_socket { bool in_use; @@ -471,6 +477,7 @@ private: static void tcpip_init_irq(void *handle); rtos::Semaphore tcpip_inited; Interface *default_interface; + LWIPMemoryManager memory_manager; }; #endif /* LWIPSTACK_H_ */ diff --git a/features/FEATURE_LWIP/lwip-interface/emac_stack_mem_lwip.c b/features/FEATURE_LWIP/lwip-interface/emac_stack_mem_lwip.c deleted file mode 100644 index d84427802c..0000000000 --- a/features/FEATURE_LWIP/lwip-interface/emac_stack_mem_lwip.c +++ /dev/null @@ -1,93 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * 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 "emac_stack_mem.h" -#include "pbuf.h" - -emac_stack_mem_t *emac_stack_mem_alloc(uint32_t size, uint32_t align) -{ - - struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, size + align, PBUF_RAM); - if (pbuf == NULL) { - return NULL; - } - - if (align) { - uint32_t remainder = (uint32_t)pbuf->payload % align; - uint32_t offset = align - remainder; - if (offset >= align) { - offset = align; - } - - pbuf->payload = (void*)((char*)pbuf->payload + offset); - pbuf->tot_len -= offset; - pbuf->len -= offset; - } - - return (emac_stack_mem_t*)pbuf; -} - -void emac_stack_mem_free(emac_stack_mem_t *mem) -{ - pbuf_free((struct pbuf*)mem); -} - -void emac_stack_mem_copy(emac_stack_mem_t *to, emac_stack_mem_t *from) -{ - pbuf_copy((struct pbuf*)to, (struct pbuf*)from); -} - -void *emac_stack_mem_ptr(emac_stack_mem_t *mem) -{ - return ((struct pbuf*)mem)->payload; -} - -uint32_t emac_stack_mem_len(emac_stack_mem_t *mem) -{ - return ((struct pbuf*)mem)->len; -} - -void emac_stack_mem_set_len(emac_stack_mem_t *mem, uint32_t len) -{ - struct pbuf *pbuf = (struct pbuf*)mem; - - pbuf->len = len; -} - -emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_mem_chain_t **chain) -{ - struct pbuf **list = (struct pbuf**)chain; - struct pbuf *head = *list; - *list = (*list)->next; - - return (emac_stack_mem_t *)head; -} - -uint32_t emac_stack_mem_chain_len(emac_stack_mem_chain_t *chain) -{ - return ((struct pbuf*)chain)->tot_len; -} - -void emac_stack_mem_set_chain_len(emac_stack_mem_chain_t *chain, uint32_t len) - { - struct pbuf *pbuf = (struct pbuf*)chain; - pbuf->tot_len = len; -} - -void emac_stack_mem_ref(emac_stack_mem_t *mem) -{ - pbuf_ref((struct pbuf*)mem); -} diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/lwipopts_conf.h b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/lwipopts_conf.h deleted file mode 100644 index 0851fd63fe..0000000000 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/lwipopts_conf.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2015 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef LWIPOPTS_CONF_H -#define LWIPOPTS_CONF_H - -#define LWIP_TRANSPORT_ETHERNET 1 - -#define MEM_SIZE (1600 * 16) - -#endif diff --git a/features/FEATURE_LWIP/lwip-interface/lwipopts.h b/features/FEATURE_LWIP/lwip-interface/lwipopts.h index 7b7d86aa62..d4bf8a9520 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwipopts.h +++ b/features/FEATURE_LWIP/lwip-interface/lwipopts.h @@ -145,7 +145,7 @@ #ifdef MBED_CONF_LWIP_PBUF_POOL_BUFSIZE #undef PBUF_POOL_BUFSIZE -#define PBUF_POOL_BUFSIZE MBED_CONF_LWIP_PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_LWIP_PBUF_POOL_BUFSIZE) #else #ifndef PBUF_POOL_BUFSIZE #if LWIP_IPV6 diff --git a/features/netsocket/EMAC.h b/features/netsocket/EMAC.h index 25f4caf710..5af593cc09 100644 --- a/features/netsocket/EMAC.h +++ b/features/netsocket/EMAC.h @@ -19,7 +19,7 @@ #include #include "Callback.h" -#include "emac_stack_mem.h" +#include "EMACMemoryManager.h" // Nuvoton platform headers define EMAC - avoid the collision #undef EMAC @@ -44,8 +44,8 @@ public: * * @param buf Received data */ - //typedef void (*emac_link_input_fn)(void *data, emac_stack_mem_chain_t *buf); - typedef mbed::Callback emac_link_input_cb_t; + //typedef void (*emac_link_input_fn)(void *data, emac_mem_buf_t *buf); + typedef mbed::Callback emac_link_input_cb_t; /** * Callback to be register with Emac interface and to be called for link status changes @@ -112,7 +112,7 @@ public: * @param buf Packet to be send * @return True if the packet was send successfully, False otherwise */ - virtual bool link_out(emac_stack_mem_chain_t *buf) = 0; + virtual bool link_out(emac_mem_buf_t *buf) = 0; /** * Initializes the HW @@ -147,6 +147,11 @@ public: */ virtual void add_multicast_group(uint8_t *address) = 0; + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr) = 0; }; diff --git a/features/netsocket/EMACMemoryManager.h b/features/netsocket/EMACMemoryManager.h new file mode 100644 index 0000000000..112b0c5bda --- /dev/null +++ b/features/netsocket/EMACMemoryManager.h @@ -0,0 +1,159 @@ +/* Copyright (c) 2017 ARM Limited + * + * 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 EMAC_MEMORY_MANAGER_H +#define EMAC_MEMORY_MANAGER_H + +/** + * Emac interface memory manager + * + * This interface provides abstraction for memory modules used in different IP stacks (often to accommodate zero + * copy). Emac 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 emacs module independent. + * + * Emac 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 Emac 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 Emac 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. + * + */ + +typedef void emac_mem_buf_t; // Memory buffer + +class EMACMemoryManager { +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 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; + + /** + * 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/emac_stack_mem.h b/features/netsocket/emac_stack_mem.h deleted file mode 100644 index b0bbd820d0..0000000000 --- a/features/netsocket/emac_stack_mem.h +++ /dev/null @@ -1,111 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * 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 MBED_EMAC_STACK_MEM_H -#define MBED_EMAC_STACK_MEM_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Stack memory module - * - * This interface provides abstraction for memory modules used in different IP stacks (often to accommodate zero copy). - * Emac interface may be required to accept output packets and provide received data using this stack specific API. - * This header should be implemented for each IP stack, so that we keep emacs module independent. - */ -typedef void emac_stack_mem_t; -typedef void emac_stack_mem_chain_t; - -/** - * Allocates stack memory - * - * @param size Size of memory to allocate - * @param align Memory alignment requirements - * @return Allocated memory struct, or NULL in case of error - */ -emac_stack_mem_t *emac_stack_mem_alloc(uint32_t size, uint32_t align); - -/** - * Free memory allocated using @a stack_mem_alloc - * - * @param mem Memory to be freed - */ -void emac_stack_mem_free(emac_stack_mem_t *mem); - -/** - * Copy memory - * - * @param to Memory to copy to - * @param from Memory to copy from - */ -void emac_stack_mem_copy(emac_stack_mem_t *to, emac_stack_mem_t *from); - -/** - * Return pointer to the payload - * - * @param mem Memory structure - * @return Pointer to the payload - */ -void *emac_stack_mem_ptr(emac_stack_mem_t *mem); - -/** - * Return actual payload size - * - * @param mem Memory structure - * @return Size in bytes - */ -uint32_t emac_stack_mem_len(emac_stack_mem_t *mem); - -/** - * Sets the actual payload size (the allocated payload size will not change) - * - * @param mem Memory structure - * @param len Actual payload size - */ -void emac_stack_mem_set_len(emac_stack_mem_t *mem, uint32_t len); - -/** - * Returns first memory structure from the list and move the head to point to the next node - * - * @param chain Pointer to the list - * @return First memory structure from the list - */ -emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_mem_chain_t **chain); - -/** - * Return total length of the memory chain - * - * @param chain Memory chain - * @return Chain length - */ -uint32_t emac_stack_mem_chain_len(emac_stack_mem_chain_t *chain); - -/** -* Set total length of the memory chain -* -* @param chain Memory chain -* @param len Total chain length - */ -void emac_stack_mem_set_chain_len(emac_stack_mem_chain_t *chain, uint32_t len); - -#ifdef __cplusplus -} -#endif - -#endif /* EMAC_MBED_STACK_MEM_h */