1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public API for network L2 interface
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_NET_NET_L2_H_
13 #define ZEPHYR_INCLUDE_NET_NET_L2_H_
14 
15 #include <zephyr/device.h>
16 #include <zephyr/net_buf.h>
17 #include <zephyr/net/net_ip.h>
18 #include <zephyr/net/capture.h>
19 #include <zephyr/sys/iterable_sections.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /**
26  * @brief Network Layer 2 abstraction layer
27  * @defgroup net_l2 Network L2 Abstraction Layer
28  * @since 1.5
29  * @version 1.0.0
30  * @ingroup networking
31  * @{
32  */
33 
34 struct net_if;
35 
36 /** L2 flags */
37 enum net_l2_flags {
38 	/** IP multicast supported */
39 	NET_L2_MULTICAST			= BIT(0),
40 
41 	/** Do not join solicited node multicast group */
42 	NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE	= BIT(1),
43 
44 	/** Is promiscuous mode supported */
45 	NET_L2_PROMISC_MODE			= BIT(2),
46 
47 	/** Is this L2 point-to-point with tunneling so no need to have
48 	 * IP address etc to network interface.
49 	 */
50 	NET_L2_POINT_TO_POINT			= BIT(3),
51 } __packed;
52 
53 /**
54  * @brief Network L2 structure
55  *
56  * Used to provide an interface to lower network stack.
57  */
58 struct net_l2 {
59 	/**
60 	 * This function is used by net core to get iface's L2 layer parsing
61 	 * what's relevant to itself.
62 	 */
63 	enum net_verdict (*recv)(struct net_if *iface, struct net_pkt *pkt);
64 
65 	/**
66 	 * This function is used by net core to push a packet to lower layer
67 	 * (interface's L2), which in turn might work on the packet relevantly.
68 	 * (adding proper header etc...)
69 	 * Returns a negative error code, or the number of bytes sent otherwise.
70 	 */
71 	int (*send)(struct net_if *iface, struct net_pkt *pkt);
72 
73 	/**
74 	 * This function is used to enable/disable traffic over a network
75 	 * interface. The function returns <0 if error and >=0 if no error.
76 	 */
77 	int (*enable)(struct net_if *iface, bool state);
78 
79 	/**
80 	 * Return L2 flags for the network interface.
81 	 */
82 	enum net_l2_flags (*get_flags)(struct net_if *iface);
83 
84 	/**
85 	 * Optional function for reserving L2 header space for this technology.
86 	 */
87 	int (*alloc)(struct net_if *iface, struct net_pkt *pkt,
88 		     size_t size, enum net_ip_protocol proto,
89 		     k_timeout_t timeout);
90 };
91 
92 /** @cond INTERNAL_HIDDEN */
93 #define NET_L2_GET_NAME(_name) _net_l2_##_name
94 #define NET_L2_DECLARE_PUBLIC(_name)					\
95 	extern const struct net_l2 NET_L2_GET_NAME(_name)
96 #define NET_L2_GET_CTX_TYPE(_name) _name##_CTX_TYPE
97 
98 #define VIRTUAL_L2		VIRTUAL
99 NET_L2_DECLARE_PUBLIC(VIRTUAL_L2);
100 
101 #define DUMMY_L2		DUMMY
102 #define DUMMY_L2_CTX_TYPE	void*
103 NET_L2_DECLARE_PUBLIC(DUMMY_L2);
104 
105 #define OFFLOADED_NETDEV_L2 OFFLOADED_NETDEV
106 NET_L2_DECLARE_PUBLIC(OFFLOADED_NETDEV_L2);
107 
108 #define ETHERNET_L2		ETHERNET
109 NET_L2_DECLARE_PUBLIC(ETHERNET_L2);
110 
111 #define PPP_L2			PPP
112 NET_L2_DECLARE_PUBLIC(PPP_L2);
113 
114 #define IEEE802154_L2		IEEE802154
115 NET_L2_DECLARE_PUBLIC(IEEE802154_L2);
116 
117 #define OPENTHREAD_L2		OPENTHREAD
118 NET_L2_DECLARE_PUBLIC(OPENTHREAD_L2);
119 
120 #define CANBUS_RAW_L2		CANBUS_RAW
121 #define CANBUS_RAW_L2_CTX_TYPE	void*
122 NET_L2_DECLARE_PUBLIC(CANBUS_RAW_L2);
123 
124 #ifdef CONFIG_NET_L2_CUSTOM_IEEE802154
125 #ifndef CUSTOM_IEEE802154_L2
126 #define CUSTOM_IEEE802154_L2	CUSTOM_IEEE802154
127 #endif
128 #define CUSTOM_IEEE802154_L2_CTX_TYPE	void*
129 NET_L2_DECLARE_PUBLIC(CUSTOM_IEEE802154_L2);
130 #endif /* CONFIG_NET_L2_CUSTOM_IEEE802154 */
131 
132 #define NET_L2_INIT(_name, _recv_fn, _send_fn, _enable_fn, _get_flags_fn, ...) \
133 	const STRUCT_SECTION_ITERABLE(net_l2,				\
134 				      NET_L2_GET_NAME(_name)) = {	\
135 		.recv = (_recv_fn),					\
136 		.send = (_send_fn),					\
137 		.enable = (_enable_fn),					\
138 		.get_flags = (_get_flags_fn),				\
139 		.alloc = COND_CODE_0(NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)), \
140 				     (NULL),				\
141 				     (GET_ARG_N(1, __VA_ARGS__))),	\
142 	}
143 
144 #define NET_L2_GET_DATA(name, sfx) _net_l2_data_##name##sfx
145 
146 #define NET_L2_DATA_INIT(name, sfx, ctx_type)				\
147 	static ctx_type NET_L2_GET_DATA(name, sfx) __used;
148 
149 typedef int (*net_l2_send_t)(const struct device *dev, struct net_pkt *pkt);
150 
net_l2_send(net_l2_send_t send_fn,const struct device * dev,struct net_if * iface,struct net_pkt * pkt)151 static inline int net_l2_send(net_l2_send_t send_fn,
152 			      const struct device *dev,
153 			      struct net_if *iface,
154 			      struct net_pkt *pkt)
155 {
156 	net_capture_pkt(iface, pkt);
157 
158 	return send_fn(dev, pkt);
159 }
160 
161 /** @endcond */
162 
163 /**
164  * @}
165  */
166 
167 #ifdef __cplusplus
168 }
169 #endif
170 
171 #endif /* ZEPHYR_INCLUDE_NET_NET_L2_H_ */
172