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