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 /** Interface this neighbor is found */
60 struct net_if *iface;
61
62 /** Pointer to the start of data in the neighbor table. */
63 uint8_t *data;
64
65 /** Function to be called when the neighbor is removed. */
66 void (*const remove)(struct net_nbr *nbr);
67
68 /** Start of the data storage. Not to be accessed directly
69 * (the data pointer should be used instead).
70 */
71 uint8_t __nbr[0] __net_nbr_align;
72 };
73
74 /* This is an array of struct net_nbr + some additional data */
75 #define NET_NBR_POOL_INIT(_name, _count, _size, _remove) \
76 struct { \
77 struct net_nbr nbr; \
78 uint8_t data[ROUND_UP(_size, 4)] __net_nbr_align; \
79 } _name[_count] = { \
80 [0 ... (_count - 1)] = { .nbr = { \
81 .idx = NET_NBR_LLADDR_UNKNOWN, \
82 .remove = _remove, \
83 .size = ROUND_UP(_size, 4) } }, \
84 }
85
86 struct net_nbr_table {
87 /** Link to a neighbor pool */
88 struct net_nbr *nbr;
89
90 /** Function to be called when the table is cleared. */
91 void (*const clear)(struct net_nbr_table *table);
92
93 /** Max number of neighbors in the pool */
94 const uint16_t nbr_count;
95 };
96
97 #define NET_NBR_LOCAL static
98 #define NET_NBR_GLOBAL
99
100 /* Type of the table can be NET_NBR_LOCAL or NET_NBR_GLOBAL
101 */
102 #define NET_NBR_TABLE_INIT(_type, _name, _pool, _clear) \
103 _type struct net_nbr_table_##_name { \
104 struct net_nbr_table table; \
105 } net_##_name __used = { \
106 .table = { \
107 .clear = _clear, \
108 .nbr = (struct net_nbr *)_pool, \
109 .nbr_count = ARRAY_SIZE(_pool), \
110 } \
111 }
112
113 /**
114 * @brief Decrement the reference count. If count goes to 0, the neighbor
115 * is released and returned to free list.
116 * @param nbr Pointer to neighbor
117 */
118 #if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
119 void net_nbr_unref_debug(struct net_nbr *nbr, const char *caller, int line);
120 #define net_nbr_unref(nbr) net_nbr_unref_debug(nbr, __func__, __LINE__)
121 #else
122 void net_nbr_unref(struct net_nbr *nbr);
123 #endif
124
125 /**
126 * @brief Increment the reference count.
127 * @param nbr Pointer to neighbor
128 * @return Pointer to neighbor
129 */
130 #if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
131 struct net_nbr *net_nbr_ref_debug(struct net_nbr *nbr, const char *caller,
132 int line);
133 #define net_nbr_ref(nbr) net_nbr_ref_debug(nbr, __func__, __LINE__)
134 #else
135 struct net_nbr *net_nbr_ref(struct net_nbr *nbr);
136 #endif
137
138 /**
139 * @brief Get a free neighbor from specific table.
140 * @param table Neighbor table
141 * @return Pointer to neighbor, NULL if no free neighbors
142 */
143 struct net_nbr *net_nbr_get(struct net_nbr_table *table);
144
145 /**
146 * @brief Find a neighbor from specific table.
147 * @param table Neighbor table
148 * @param iface Network interface to use
149 * @param lladdr Neighbor link layer address
150 * @return Pointer to neighbor, NULL if not found
151 */
152 struct net_nbr *net_nbr_lookup(struct net_nbr_table *table,
153 struct net_if *iface,
154 struct net_linkaddr *lladdr);
155
156 /**
157 * @brief Link a neighbor to specific link layer address.
158 * @param table Neighbor table
159 * @param iface Network interface to use
160 * @param lladdr Neighbor link layer address
161 * @return 0 if ok, <0 if linking failed
162 */
163 int net_nbr_link(struct net_nbr *nbr, struct net_if *iface,
164 const struct net_linkaddr *lladdr);
165
166 /**
167 * @brief Unlink a neighbor from specific link layer address.
168 * @param table Neighbor table
169 * @param lladdr Neighbor link layer address
170 * @return 0 if ok, <0 if unlinking failed
171 */
172 int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr);
173
174 /**
175 * @brief Return link address for a specific lladdr table index
176 * @param idx Link layer address index in ll table.
177 * @return Pointer to link layer address storage, NULL if not found
178 */
179 #if defined(CONFIG_NET_NATIVE)
180 struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx);
181 #else
net_nbr_get_lladdr(uint8_t idx)182 static inline struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx)
183 {
184 ARG_UNUSED(idx);
185
186 return NULL;
187 }
188 #endif
189
190 /**
191 * @brief Clear table from all neighbors. After this the linking between
192 * lladdr and neighbor is removed.
193 * @param table Neighbor table
194 */
195 void net_nbr_clear_table(struct net_nbr_table *table);
196
197 /**
198 * @brief Debug helper to print out the neighbor information.
199 * @param table Neighbor table
200 */
201 void net_nbr_print(struct net_nbr_table *table);
202
203 #ifdef __cplusplus
204 }
205 #endif
206
207 #endif /* __NET_NBR_H */
208