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