| /** @file |
| * @brief IPv6 neighbor management. |
| */ |
| |
| /* |
| * Copyright (c) 2016 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #ifndef __NET_NBR_H |
| #define __NET_NBR_H |
| |
| #include <stddef.h> |
| #include <zephyr/types.h> |
| #include <stdbool.h> |
| |
| #include <net/net_if.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #define NET_NBR_LLADDR_UNKNOWN 0xff |
| |
| /* The neighbors are tracked by link layer address. This is not part |
| * of struct net_nbr because this data can be shared between different |
| * neighboring tables. |
| */ |
| struct net_nbr_lladdr { |
| /** Link layer address */ |
| struct net_linkaddr_storage lladdr; |
| |
| /** Reference count. */ |
| uint8_t ref; |
| }; |
| |
| #define NET_NBR_LLADDR_INIT(_name, _count) \ |
| struct net_nbr_lladdr _name[_count] = { } |
| |
| /* Alignment needed for various parts of the neighbor definition */ |
| #define __net_nbr_align __aligned(sizeof(int)) |
| |
| /* The neighbor node generic data. There can be sub-system specific |
| * data at the end of the node. |
| */ |
| struct net_nbr { |
| /** Reference count. */ |
| uint8_t ref; |
| |
| /** Link to ll address. This is the index into lladdr array. |
| * The value NET_NBR_LLADDR_UNKNOWN tells that this neighbor |
| * does not yet have lladdr linked to it. |
| */ |
| uint8_t idx; |
| |
| /** Amount of data that this neighbor buffer can store. */ |
| const uint16_t size; |
| |
| /** Extra data size associated with this neighbor */ |
| const uint16_t extra_data_size; |
| |
| /** Interface this neighbor is found */ |
| struct net_if *iface; |
| |
| /** Pointer to the start of data in the neighbor table. */ |
| uint8_t *data; |
| |
| /** Function to be called when the neighbor is removed. */ |
| void (*const remove)(struct net_nbr *nbr); |
| |
| /** Start of the data storage. Not to be accessed directly |
| * (the data pointer should be used instead). |
| */ |
| uint8_t __nbr[0] __net_nbr_align; |
| }; |
| |
| /* This is an array of struct net_nbr + some additional data */ |
| #define NET_NBR_POOL_INIT(_name, _count, _size, _remove, _extra_size) \ |
| struct { \ |
| struct net_nbr nbr; \ |
| uint8_t data[ROUND_UP(_size, 4)] __net_nbr_align; \ |
| uint8_t extra[ROUND_UP(_extra_size, 4)] __net_nbr_align;\ |
| } _name[_count] = { \ |
| [0 ... (_count - 1)] = { .nbr = { \ |
| .idx = NET_NBR_LLADDR_UNKNOWN, \ |
| .remove = _remove, \ |
| .size = ROUND_UP(_size, 4), \ |
| .extra_data_size = ROUND_UP(_extra_size, 4) } },\ |
| } |
| |
| struct net_nbr_table { |
| /** Link to a neighbor pool */ |
| struct net_nbr *nbr; |
| |
| /** Function to be called when the table is cleared. */ |
| void (*const clear)(struct net_nbr_table *table); |
| |
| /** Max number of neighbors in the pool */ |
| const uint16_t nbr_count; |
| }; |
| |
| #define NET_NBR_LOCAL static |
| #define NET_NBR_GLOBAL |
| |
| /* Type of the table can be NET_NBR_LOCAL or NET_NBR_GLOBAL |
| */ |
| #define NET_NBR_TABLE_INIT(_type, _name, _pool, _clear) \ |
| _type struct net_nbr_table_##_name { \ |
| struct net_nbr_table table; \ |
| } net_##_name __used = { \ |
| .table = { \ |
| .clear = _clear, \ |
| .nbr = (struct net_nbr *)_pool, \ |
| .nbr_count = ARRAY_SIZE(_pool), \ |
| } \ |
| } |
| |
| /** |
| * @brief Get a pointer to the extra data of a neighbor entry. |
| * |
| * @param nbr A valid pointer to neighbor |
| * |
| * @return Pointer to the extra data of the nbr. |
| */ |
| static inline void *net_nbr_extra_data(struct net_nbr *nbr) |
| { |
| return (void *)ROUND_UP((nbr->__nbr + nbr->size), sizeof(int)); |
| } |
| |
| /** |
| * @brief Decrement the reference count. If count goes to 0, the neighbor |
| * is released and returned to free list. |
| * @param nbr Pointer to neighbor |
| */ |
| #if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG) |
| void net_nbr_unref_debug(struct net_nbr *nbr, const char *caller, int line); |
| #define net_nbr_unref(nbr) net_nbr_unref_debug(nbr, __func__, __LINE__) |
| #else |
| void net_nbr_unref(struct net_nbr *nbr); |
| #endif |
| |
| /** |
| * @brief Increment the reference count. |
| * @param nbr Pointer to neighbor |
| * @return Pointer to neighbor |
| */ |
| #if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG) |
| struct net_nbr *net_nbr_ref_debug(struct net_nbr *nbr, const char *caller, |
| int line); |
| #define net_nbr_ref(nbr) net_nbr_ref_debug(nbr, __func__, __LINE__) |
| #else |
| struct net_nbr *net_nbr_ref(struct net_nbr *nbr); |
| #endif |
| |
| /** |
| * @brief Get a free neighbor from specific table. |
| * @param table Neighbor table |
| * @return Pointer to neighbor, NULL if no free neighbors |
| */ |
| struct net_nbr *net_nbr_get(struct net_nbr_table *table); |
| |
| /** |
| * @brief Find a neighbor from specific table. |
| * @param table Neighbor table |
| * @param iface Network interface to use |
| * @param lladdr Neighbor link layer address |
| * @return Pointer to neighbor, NULL if not found |
| */ |
| struct net_nbr *net_nbr_lookup(struct net_nbr_table *table, |
| struct net_if *iface, |
| struct net_linkaddr *lladdr); |
| |
| /** |
| * @brief Link a neighbor to specific link layer address. |
| * @param table Neighbor table |
| * @param iface Network interface to use |
| * @param lladdr Neighbor link layer address |
| * @return 0 if ok, <0 if linking failed |
| */ |
| int net_nbr_link(struct net_nbr *nbr, struct net_if *iface, |
| const struct net_linkaddr *lladdr); |
| |
| /** |
| * @brief Unlink a neighbor from specific link layer address. |
| * @param table Neighbor table |
| * @param lladdr Neighbor link layer address |
| * @return 0 if ok, <0 if unlinking failed |
| */ |
| int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr); |
| |
| /** |
| * @brief Return link address for a specific lladdr table index |
| * @param idx Link layer address index in ll table. |
| * @return Pointer to link layer address storage, NULL if not found |
| */ |
| #if defined(CONFIG_NET_NATIVE) |
| struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx); |
| #else |
| static inline struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx) |
| { |
| ARG_UNUSED(idx); |
| |
| return NULL; |
| } |
| #endif |
| |
| /** |
| * @brief Clear table from all neighbors. After this the linking between |
| * lladdr and neighbor is removed. |
| * @param table Neighbor table |
| */ |
| void net_nbr_clear_table(struct net_nbr_table *table); |
| |
| /** |
| * @brief Debug helper to print out the neighbor information. |
| * @param table Neighbor table |
| */ |
| void net_nbr_print(struct net_nbr_table *table); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __NET_NBR_H */ |