1 /** @file
2 * @brief IPv6 neighbor management.
3 */
4
5 /*
6 * Copyright (c) 2016 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10 #ifndef __NET_NBR_H
11 #define __NET_NBR_H
12
13 #include <stddef.h>
14 #include <zephyr/types.h>
15 #include <stdbool.h>
16
17 #include <zephyr/net/net_if.h>
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 #define NET_NBR_LLADDR_UNKNOWN 0xff
24
25 /* The neighbors are tracked by link layer address. This is not part
26 * of struct net_nbr because this data can be shared between different
27 * neighboring tables.
28 */
29 struct net_nbr_lladdr {
30 /** Link layer address */
31 struct net_linkaddr_storage lladdr;
32
33 /** Reference count. */
34 uint8_t ref;
35 };
36
37 #define NET_NBR_LLADDR_INIT(_name, _count) \
38 struct net_nbr_lladdr _name[_count] = { }
39
40 /* Alignment needed for various parts of the neighbor definition */
41 #define __net_nbr_align __aligned(sizeof(int))
42
43 /* The neighbor node generic data. There can be sub-system specific
44 * data at the end of the node.
45 */
46 struct net_nbr {
47 /** Reference count. */
48 uint8_t ref;
49
50 /** Link to ll address. This is the index into lladdr array.
51 * The value NET_NBR_LLADDR_UNKNOWN tells that this neighbor
52 * does not yet have lladdr linked to it.
53 */
54 uint8_t idx;
55
56 /** Amount of data that this neighbor buffer can store. */
57 const uint16_t size;
58
59 /** Extra data size associated with this neighbor */
60 const uint16_t extra_data_size;
61
62 /** Interface this neighbor is found */
63 struct net_if *iface;
64
65 /** Pointer to the start of data in the neighbor table. */
66 uint8_t *data;
67
68 /** Function to be called when the neighbor is removed. */
69 void (*const remove)(struct net_nbr *nbr);
70
71 /** Start of the data storage. Not to be accessed directly
72 * (the data pointer should be used instead).
73 */
74 uint8_t __nbr[0] __net_nbr_align;
75 };
76
77 /* This is an array of struct net_nbr + some additional data */
78 #define NET_NBR_POOL_INIT(_name, _count, _size, _remove, _extra_size) \
79 struct { \
80 struct net_nbr nbr; \
81 uint8_t data[ROUND_UP(_size, 4)] __net_nbr_align; \
82 uint8_t extra[ROUND_UP(_extra_size, 4)] __net_nbr_align;\
83 } _name[_count] = { \
84 [0 ... (_count - 1)] = { .nbr = { \
85 .idx = NET_NBR_LLADDR_UNKNOWN, \
86 .remove = _remove, \
87 .size = ROUND_UP(_size, 4), \
88 .extra_data_size = ROUND_UP(_extra_size, 4) } },\
89 }
90
91 struct net_nbr_table {
92 /** Link to a neighbor pool */
93 struct net_nbr *nbr;
94
95 /** Function to be called when the table is cleared. */
96 void (*const clear)(struct net_nbr_table *table);
97
98 /** Max number of neighbors in the pool */
99 const uint16_t nbr_count;
100 };
101
102 #define NET_NBR_LOCAL static
103 #define NET_NBR_GLOBAL
104
105 /* Type of the table can be NET_NBR_LOCAL or NET_NBR_GLOBAL
106 */
107 #define NET_NBR_TABLE_INIT(_type, _name, _pool, _clear) \
108 _type struct net_nbr_table_##_name { \
109 struct net_nbr_table table; \
110 } net_##_name __used = { \
111 .table = { \
112 .clear = _clear, \
113 .nbr = (struct net_nbr *)_pool, \
114 .nbr_count = ARRAY_SIZE(_pool), \
115 } \
116 }
117
118 /**
119 * @brief Get a pointer to the extra data of a neighbor entry.
120 *
121 * @param nbr A valid pointer to neighbor
122 *
123 * @return Pointer to the extra data of the nbr.
124 */
net_nbr_extra_data(struct net_nbr * nbr)125 static inline void *net_nbr_extra_data(struct net_nbr *nbr)
126 {
127 return (void *)ROUND_UP((nbr->__nbr + nbr->size), sizeof(int));
128 }
129
130 /**
131 * @brief Decrement the reference count. If count goes to 0, the neighbor
132 * is released and returned to free list.
133 * @param nbr Pointer to neighbor
134 */
135 #if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
136 void net_nbr_unref_debug(struct net_nbr *nbr, const char *caller, int line);
137 #define net_nbr_unref(nbr) net_nbr_unref_debug(nbr, __func__, __LINE__)
138 #else
139 void net_nbr_unref(struct net_nbr *nbr);
140 #endif
141
142 /**
143 * @brief Increment the reference count.
144 * @param nbr Pointer to neighbor
145 * @return Pointer to neighbor
146 */
147 #if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
148 struct net_nbr *net_nbr_ref_debug(struct net_nbr *nbr, const char *caller,
149 int line);
150 #define net_nbr_ref(nbr) net_nbr_ref_debug(nbr, __func__, __LINE__)
151 #else
152 struct net_nbr *net_nbr_ref(struct net_nbr *nbr);
153 #endif
154
155 /**
156 * @brief Get a free neighbor from specific table.
157 * @param table Neighbor table
158 * @return Pointer to neighbor, NULL if no free neighbors
159 */
160 struct net_nbr *net_nbr_get(struct net_nbr_table *table);
161
162 /**
163 * @brief Find a neighbor from specific table.
164 * @param table Neighbor table
165 * @param iface Network interface to use
166 * @param lladdr Neighbor link layer address
167 * @return Pointer to neighbor, NULL if not found
168 */
169 struct net_nbr *net_nbr_lookup(struct net_nbr_table *table,
170 struct net_if *iface,
171 struct net_linkaddr *lladdr);
172
173 /**
174 * @brief Link a neighbor to specific link layer address.
175 * @param table Neighbor table
176 * @param iface Network interface to use
177 * @param lladdr Neighbor link layer address
178 * @return 0 if ok, <0 if linking failed
179 */
180 int net_nbr_link(struct net_nbr *nbr, struct net_if *iface,
181 const struct net_linkaddr *lladdr);
182
183 /**
184 * @brief Unlink a neighbor from specific link layer address.
185 * @param table Neighbor table
186 * @param lladdr Neighbor link layer address
187 * @return 0 if ok, <0 if unlinking failed
188 */
189 int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr);
190
191 /**
192 * @brief Return link address for a specific lladdr table index
193 * @param idx Link layer address index in ll table.
194 * @return Pointer to link layer address storage, NULL if not found
195 */
196 #if defined(CONFIG_NET_NATIVE)
197 struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx);
198 #else
net_nbr_get_lladdr(uint8_t idx)199 static inline struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx)
200 {
201 ARG_UNUSED(idx);
202
203 return NULL;
204 }
205 #endif
206
207 /**
208 * @brief Clear table from all neighbors. After this the linking between
209 * lladdr and neighbor is removed.
210 * @param table Neighbor table
211 */
212 void net_nbr_clear_table(struct net_nbr_table *table);
213
214 /**
215 * @brief Debug helper to print out the neighbor information.
216 * @param table Neighbor table
217 */
218 void net_nbr_print(struct net_nbr_table *table);
219
220 #ifdef __cplusplus
221 }
222 #endif
223
224 #endif /* __NET_NBR_H */
225