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