1 /** @file
2 * @brief Virtual Network Interface
3 */
4
5 /*
6 * Copyright (c) 2021 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #ifndef ZEPHYR_INCLUDE_NET_VIRTUAL_H_
12 #define ZEPHYR_INCLUDE_NET_VIRTUAL_H_
13
14 #include <zephyr/kernel.h>
15 #include <zephyr/types.h>
16 #include <stdbool.h>
17 #include <zephyr/sys/atomic.h>
18
19 #include <zephyr/net/net_ip.h>
20 #include <zephyr/net/net_pkt.h>
21
22 #include <zephyr/sys/util.h>
23 #include <zephyr/net/net_if.h>
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 /**
30 * @brief Virtual network interface support functions
31 * @defgroup virtual Virtual Network Interface Support Functions
32 * @since 2.6
33 * @version 0.8.0
34 * @ingroup networking
35 * @{
36 */
37
38 /** Virtual interface capabilities */
39 enum virtual_interface_caps {
40 /** IPIP tunnel */
41 VIRTUAL_INTERFACE_IPIP = BIT(1),
42
43 /** Virtual LAN interface (VLAN) */
44 VIRTUAL_INTERFACE_VLAN = BIT(2),
45
46 /** Virtual Ethernet bridge interface. */
47 VIRTUAL_INTERFACE_BRIDGE = BIT(3),
48
49 /** VPN interface */
50 VIRTUAL_INTERFACE_VPN = BIT(4),
51
52 /** @cond INTERNAL_HIDDEN */
53 /* Marker for capabilities - must be at the end of the enum.
54 * It is here because the capability list cannot be empty.
55 */
56 VIRTUAL_INTERFACE_NUM_CAPS
57 /** @endcond */
58 };
59
60 /** @cond INTERNAL_HIDDEN */
61
62 enum virtual_interface_config_type {
63 VIRTUAL_INTERFACE_CONFIG_TYPE_PEER_ADDRESS,
64 VIRTUAL_INTERFACE_CONFIG_TYPE_MTU,
65 VIRTUAL_INTERFACE_CONFIG_TYPE_LINK_TYPE,
66 VIRTUAL_INTERFACE_CONFIG_TYPE_PRIVATE_KEY,
67 VIRTUAL_INTERFACE_CONFIG_TYPE_PUBLIC_KEY,
68 };
69
70 struct virtual_interface_link_types {
71 int count;
72 uint16_t type[COND_CODE_1(CONFIG_NET_CAPTURE_COOKED_MODE,
73 (CONFIG_NET_CAPTURE_COOKED_MODE_MAX_LINK_TYPES),
74 (1))];
75 };
76
77 #if !defined(NET_VIRTUAL_MAX_PUBLIC_KEY_LEN)
78 #define NET_VIRTUAL_MAX_PUBLIC_KEY_LEN 32U
79 #endif
80
81 struct virtual_interface_config {
82 net_sa_family_t family;
83 union {
84 struct net_in_addr peer4addr;
85 struct net_in6_addr peer6addr;
86 int mtu;
87 struct virtual_interface_link_types link_types;
88 struct {
89 size_t len;
90 uint8_t *data;
91 } private_key;
92 struct {
93 size_t len;
94 uint8_t data[NET_VIRTUAL_MAX_PUBLIC_KEY_LEN];
95 } public_key;
96 };
97 };
98
99 #if defined(CONFIG_NET_L2_VIRTUAL)
100 #define VIRTUAL_MAX_NAME_LEN CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN
101 #else
102 #define VIRTUAL_MAX_NAME_LEN 0
103 #endif
104 /** @endcond */
105
106 /** Virtual L2 API operations. */
107 struct virtual_interface_api {
108 /**
109 * The net_if_api must be placed in first position in this
110 * struct so that we are compatible with network interface API.
111 */
112 struct net_if_api iface_api;
113
114 /** Get the virtual interface capabilities */
115 enum virtual_interface_caps (*get_capabilities)(struct net_if *iface);
116
117 /** Start the device */
118 int (*start)(const struct device *dev);
119
120 /** Stop the device */
121 int (*stop)(const struct device *dev);
122
123 /** Send a network packet */
124 int (*send)(struct net_if *iface, struct net_pkt *pkt);
125
126 /**
127 * Receive a network packet.
128 * The callback returns NET_OK if this interface will accept the
129 * packet and pass it upper layers, NET_DROP if the packet is to be
130 * dropped and NET_CONTINUE to pass it to next interface.
131 */
132 enum net_verdict (*recv)(struct net_if *iface, struct net_pkt *pkt);
133
134 /** Pass the attachment information to virtual interface */
135 int (*attach)(struct net_if *virtual_iface, struct net_if *iface);
136
137 /** Set specific L2 configuration */
138 int (*set_config)(struct net_if *iface,
139 enum virtual_interface_config_type type,
140 const struct virtual_interface_config *config);
141
142 /** Get specific L2 configuration */
143 int (*get_config)(struct net_if *iface,
144 enum virtual_interface_config_type type,
145 struct virtual_interface_config *config);
146 };
147
148 /* Make sure that the network interface API is properly setup inside
149 * Virtual API struct (it is the first one).
150 */
151 BUILD_ASSERT(offsetof(struct virtual_interface_api, iface_api) == 0);
152
153 /** Virtual L2 context that is needed to binding to the real network interface
154 */
155 struct virtual_interface_context {
156 /** @cond INTERNAL_HIDDEN */
157 /* Keep track of contexts */
158 sys_snode_t node;
159
160 /* My virtual network interface */
161 struct net_if *virtual_iface;
162 /** @endcond */
163
164 /**
165 * Other network interface this virtual network interface is
166 * attached to. These values can be chained so virtual network
167 * interfaces can run on top of other virtual interfaces.
168 */
169 struct net_if *iface;
170
171 /**
172 * This tells what L2 features does virtual support.
173 */
174 enum net_l2_flags virtual_l2_flags;
175
176 /** Is this context already initialized */
177 bool is_init;
178
179 /** Link address for this network interface */
180 struct net_linkaddr lladdr;
181
182 /** User friendly name of this L2 layer. */
183 char name[VIRTUAL_MAX_NAME_LEN];
184 };
185
186 /**
187 * @brief Attach virtual network interface to the given network interface.
188 *
189 * @param virtual_iface Virtual network interface.
190 * @param iface Network interface we are attached to. This can be NULL,
191 * if we want to detach.
192 *
193 * @return 0 if ok, <0 if attaching failed
194 */
195 int net_virtual_interface_attach(struct net_if *virtual_iface,
196 struct net_if *iface);
197
198 /**
199 * @brief Return network interface related to this virtual network interface.
200 * The returned network interface is below this virtual network interface.
201 *
202 * @param iface Virtual network interface.
203 *
204 * @return Network interface related to this virtual interface or
205 * NULL if no such interface exists.
206 */
207 struct net_if *net_virtual_get_iface(struct net_if *iface);
208
209 /**
210 * @brief Return the name of the virtual network interface L2.
211 *
212 * @param iface Virtual network interface.
213 * @param buf Buffer to store the name
214 * @param len Max buffer length
215 *
216 * @return Name of the virtual network interface.
217 */
218 char *net_virtual_get_name(struct net_if *iface, char *buf, size_t len);
219
220 /**
221 * @brief Set the name of the virtual network interface L2.
222 *
223 * @param iface Virtual network interface.
224 * @param name Name of the virtual L2 layer.
225 */
226 void net_virtual_set_name(struct net_if *iface, const char *name);
227
228 /**
229 * @brief Set the L2 flags of the virtual network interface.
230 *
231 * @param iface Virtual network interface.
232 * @param flags L2 flags to set.
233 *
234 * @return Previous flags that were set.
235 */
236 enum net_l2_flags net_virtual_set_flags(struct net_if *iface,
237 enum net_l2_flags flags);
238
239 /**
240 * @brief Feed the IP pkt to stack if tunneling is enabled.
241 *
242 * @param input_iface Network interface receiving the pkt.
243 * @param remote_addr IP address of the sender.
244 * @param pkt Network packet.
245 *
246 * @return Verdict what to do with the packet.
247 */
248 enum net_verdict net_virtual_input(struct net_if *input_iface,
249 struct net_addr *remote_addr,
250 struct net_pkt *pkt);
251
252 /** @cond INTERNAL_HIDDEN */
253
254 /**
255 * @brief Initialize the network interface so that a virtual
256 * interface can be attached to it.
257 *
258 * @param iface Network interface
259 */
260 #if defined(CONFIG_NET_L2_VIRTUAL)
261 void net_virtual_init(struct net_if *iface);
262 #else
net_virtual_init(struct net_if * iface)263 static inline void net_virtual_init(struct net_if *iface)
264 {
265 ARG_UNUSED(iface);
266 }
267 #endif
268
269 /**
270 * @brief Update the carrier state of the virtual network interface.
271 * This is called if the underlying interface is going down.
272 *
273 * @param iface Network interface
274 */
275 #if defined(CONFIG_NET_L2_VIRTUAL)
276 void net_virtual_disable(struct net_if *iface);
277 #else
net_virtual_disable(struct net_if * iface)278 static inline void net_virtual_disable(struct net_if *iface)
279 {
280 ARG_UNUSED(iface);
281 }
282 #endif
283
284 /**
285 * @brief Update the carrier state of the virtual network interface.
286 * This is called if the underlying interface is going up.
287 *
288 * @param iface Network interface
289 */
290 #if defined(CONFIG_NET_L2_VIRTUAL)
291 void net_virtual_enable(struct net_if *iface);
292 #else
net_virtual_enable(struct net_if * iface)293 static inline void net_virtual_enable(struct net_if *iface)
294 {
295 ARG_UNUSED(iface);
296 }
297 #endif
298
299 #define VIRTUAL_L2_CTX_TYPE struct virtual_interface_context
300
301 /**
302 * @brief Return virtual device hardware capability information.
303 *
304 * @param iface Network interface
305 *
306 * @return Hardware capabilities
307 */
308 static inline enum virtual_interface_caps
net_virtual_get_iface_capabilities(struct net_if * iface)309 net_virtual_get_iface_capabilities(struct net_if *iface)
310 {
311 const struct virtual_interface_api *virt =
312 (struct virtual_interface_api *)net_if_get_device(iface)->api;
313
314 if (!virt->get_capabilities) {
315 return (enum virtual_interface_caps)0;
316 }
317
318 return virt->get_capabilities(iface);
319 }
320
321 #define Z_NET_VIRTUAL_INTERFACE_INIT(node_id, dev_id, name, init_fn, \
322 pm, data, config, prio, api, mtu) \
323 Z_NET_DEVICE_INIT(node_id, dev_id, name, init_fn, pm, data, \
324 config, prio, api, VIRTUAL_L2, \
325 NET_L2_GET_CTX_TYPE(VIRTUAL_L2), mtu)
326
327 #define Z_NET_VIRTUAL_INTERFACE_INIT_INSTANCE(node_id, dev_id, name, \
328 inst, init_fn, pm, data, \
329 config, prio, api, mtu) \
330 Z_NET_DEVICE_INIT_INSTANCE(node_id, dev_id, name, inst, \
331 init_fn, pm, data, \
332 config, prio, api, VIRTUAL_L2, \
333 NET_L2_GET_CTX_TYPE(VIRTUAL_L2), mtu)
334 /** @endcond */
335
336 /**
337 * @brief Create a virtual network interface. Binding to another interface
338 * is done at runtime by calling net_virtual_interface_attach().
339 * The attaching is done automatically when setting up tunneling
340 * when peer IP address is set in IP tunneling driver.
341 *
342 * @param dev_id Network device id.
343 * @param name The name this instance of the driver exposes to
344 * the system.
345 * @param init_fn Address to the init function of the driver.
346 * @param pm Reference to struct pm_device associated with the device.
347 * (optional).
348 * @param data Pointer to the device's private data.
349 * @param config The address to the structure containing the
350 * configuration information for this instance of the driver.
351 * @param prio The initialization level at which configuration occurs.
352 * @param api Provides an initial pointer to the API function struct
353 * used by the driver. Can be NULL.
354 * @param mtu Maximum transfer unit in bytes for this network interface.
355 * This is the default value and its value can be tweaked at runtime.
356 */
357 #define NET_VIRTUAL_INTERFACE_INIT(dev_id, name, init_fn, pm, data, \
358 config, prio, api, mtu) \
359 Z_NET_VIRTUAL_INTERFACE_INIT(DT_INVALID_NODE, dev_id, name, \
360 init_fn, pm, data, config, prio, \
361 api, mtu)
362
363 /**
364 * @brief Create a virtual network interface. Binding to another interface
365 * is done at runtime by calling net_virtual_interface_attach().
366 * The attaching is done automatically when setting up tunneling
367 * when peer IP address is set in IP tunneling driver.
368 *
369 * @param dev_id Network device id.
370 * @param name The name this instance of the driver exposes to
371 * the system.
372 * @param inst instance number
373 * @param init_fn Address to the init function of the driver.
374 * @param pm Reference to struct pm_device associated with the device.
375 * (optional).
376 * @param data Pointer to the device's private data.
377 * @param config The address to the structure containing the
378 * configuration information for this instance of the driver.
379 * @param prio The initialization level at which configuration occurs.
380 * @param api Provides an initial pointer to the API function struct
381 * used by the driver. Can be NULL.
382 * @param mtu Maximum transfer unit in bytes for this network interface.
383 * This is the default value and its value can be tweaked at runtime.
384 */
385 #define NET_VIRTUAL_INTERFACE_INIT_INSTANCE(dev_id, name, inst, \
386 init_fn, pm, data, \
387 config, prio, api, mtu) \
388 Z_NET_VIRTUAL_INTERFACE_INIT_INSTANCE(DT_INVALID_NODE, dev_id, \
389 name, inst, \
390 init_fn, pm, data, config, \
391 prio, api, mtu)
392
393 /**
394 * @}
395 */
396
397 #ifdef __cplusplus
398 }
399 #endif
400
401 #endif /* ZEPHYR_INCLUDE_NET_VIRTUAL_H_ */
402