/** @file * @brief Network core definitions * * Definitions for networking support. */ /* * Copyright (c) 2015 Intel Corporation * * 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_CORE_H #define __NET_CORE_H #ifdef __cplusplus extern "C" { #endif /* Network subsystem logging helpers */ #if defined(NET_LOG_ENABLED) #if !defined(SYS_LOG_DOMAIN) #define SYS_LOG_DOMAIN "net" #endif /* !SYS_LOG_DOMAIN */ #undef SYS_LOG_LEVEL #ifndef NET_SYS_LOG_LEVEL #define SYS_LOG_LEVEL CONFIG_SYS_LOG_NET_LEVEL #else #define SYS_LOG_LEVEL NET_SYS_LOG_LEVEL #endif /* !NET_SYS_LOG_LEVEL */ #define NET_DBG(fmt, ...) SYS_LOG_DBG("(%p): " fmt, k_current_get(), \ ##__VA_ARGS__) #define NET_ERR(fmt, ...) SYS_LOG_ERR(fmt, ##__VA_ARGS__) #define NET_WARN(fmt, ...) SYS_LOG_WRN(fmt, ##__VA_ARGS__) #define NET_INFO(fmt, ...) SYS_LOG_INF(fmt, ##__VA_ARGS__) #define NET_ASSERT(cond) do { \ if (!(cond)) { \ NET_ERR("{assert: '" #cond "' failed}"); \ } } while (0) #define NET_ASSERT_INFO(cond, fmt, ...) do { \ if (!(cond)) { \ NET_ERR("{assert: '" #cond "' failed} " fmt, \ ##__VA_ARGS__); \ } } while (0) #else /* NET_LOG_ENABLED */ #define NET_DBG(...) #define NET_ERR(...) #define NET_INFO(...) #define NET_WARN(...) #define NET_ASSERT(...) #define NET_ASSERT_INFO(...) #endif /* NET_LOG_ENABLED */ #include struct net_buf; struct net_context; struct net_if; #include #include enum net_verdict { NET_OK, /** Packet has been taken care of */ NET_CONTINUE, /** Packet has not been touched, other part should decide about its fate */ NET_DROP, /** Packet must be dropped */ }; /* Called by lower network stack when a network packet has been received */ int net_recv_data(struct net_if *iface, struct net_buf *buf); /** * @brief Send data to network. * * @details Send data to network. This should not be used normally by * applications as it requires that the buffer and fragments are properly * constructed. * * @param buf Network buffer. * * @return 0 if ok, <0 if error. If <0 is returned, then the caller needs * to unref the buf in order to avoid buffer leak. */ int net_send_data(struct net_buf *buf); struct net_stack_info { unsigned char *stack; const char *pretty_name; const char *name; size_t orig_size; size_t size; }; #if defined(CONFIG_NET_SHELL) #define NET_STACK_GET_NAME(pretty, name, sfx) \ (__net_stack_##pretty##_##name##_##sfx) #define NET_STACK_INFO_ADDR(_pretty, _name, _orig, _size, _addr, sfx) \ static struct net_stack_info \ (NET_STACK_GET_NAME(_pretty, _name, sfx)) __used \ __attribute__((__section__(".net_stack.data"))) = { \ .stack = _addr, \ .size = _size, \ .orig_size = _orig, \ .name = #_name, \ .pretty_name = #_pretty, \ } #define NET_STACK_INFO(_pretty_name, _name, _orig, _size) \ NET_STACK_INFO_ADDR(_pretty_name, _name, _orig, _size, _name, 0) #define NET_STACK_DEFINE(pretty_name, name, orig, size) \ static unsigned char __noinit __stack name[size]; \ NET_STACK_INFO(pretty_name, name, orig, size) #else /* CONFIG_NET_SHELL */ #define NET_STACK_INFO(...) #define NET_STACK_INFO_ADDR(...) #define NET_STACK_DEFINE(pretty_name, name, orig, size) \ static unsigned char __noinit __stack name[size] #endif /* CONFIG_NET_SHELL */ #define NET_STACK_DEFINE_EMBEDDED(name, size) unsigned char name[size] /** @cond ignore */ #if defined(CONFIG_INIT_STACKS) #include static inline void net_analyze_stack_get_values(unsigned char *stack, size_t size, unsigned *stack_offset, unsigned *pcnt, unsigned *unused) { unsigned i; *unused = 0; /* The TCS is always placed on a 4-byte aligned boundary - if * the stack beginning doesn't match that there will be some * unused bytes in the beginning. */ *stack_offset = K_THREAD_SIZEOF + ((4 - ((unsigned)stack % 4)) % 4); /* TODO * Currently all supported platforms have stack growth down and there is no * Kconfig option to configure it so this always build "else" branch. * When support for platform with stack direction up (or configurable direction) * is added this check should be confirmed that correct Kconfig option is used. */ #if defined(CONFIG_STACK_GROWS_UP) for (i = size - 1; i >= *stack_offset; i--) { if ((unsigned char)stack[i] == 0xaa) { (*unused)++; } else { break; } } #else for (i = *stack_offset; i < size; i++) { if ((unsigned char)stack[i] == 0xaa) { (*unused)++; } else { break; } } #endif /* Calculate the real size reserved for the stack */ size -= *stack_offset; *pcnt = ((size - *unused) * 100) / size; } static inline void net_analyze_stack(const char *name, unsigned char *stack, size_t size) { unsigned stack_offset, pcnt, unused; net_analyze_stack_get_values(stack, size, &stack_offset, &pcnt, &unused); NET_INFO("net (%p): %s stack real size %zu " "unused %u usage %zu/%zu (%u %%)", k_current_get(), name, size + stack_offset, unused, size - unused, size, pcnt); } #else #define net_analyze_stack(...) #define net_analyze_stack_get_values(...) #endif /* @endcond */ #ifdef __cplusplus } #endif #endif /* __NET_CORE_H */