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