1 /** @file
2  * @brief Ethernet Bridge public header file
3  *
4  * Ethernet Bridges connect two or more Ethernet networks together and
5  * transparently forward packets from one network to the others as if
6  * they were part of the same network.
7  */
8 
9 /*
10  * Copyright (c) 2021 BayLibre SAS
11  *
12  * SPDX-License-Identifier: Apache-2.0
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_NET_ETHERNET_BRIDGE_H_
16 #define ZEPHYR_INCLUDE_NET_ETHERNET_BRIDGE_H_
17 
18 #include <zephyr/sys/slist.h>
19 #include <zephyr/sys/iterable_sections.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /**
26  * @brief Ethernet Bridging API
27  * @defgroup eth_bridge Ethernet Bridging API
28  * @since 2.7
29  * @version 0.8.0
30  * @ingroup networking
31  * @{
32  */
33 
34 /** @cond INTERNAL_HIDDEN */
35 
36 struct eth_bridge {
37 	struct k_mutex lock;
38 	sys_slist_t interfaces;
39 	sys_slist_t listeners;
40 	bool initialized;
41 };
42 
43 #define ETH_BRIDGE_INITIALIZER(obj) \
44 	{ \
45 		.lock		= { }, \
46 		.interfaces	= SYS_SLIST_STATIC_INIT(&obj.interfaces), \
47 		.listeners	= SYS_SLIST_STATIC_INIT(&obj.listeners), \
48 	}
49 
50 /** @endcond */
51 
52 /**
53  * @brief Statically define and initialize a bridge instance.
54  *
55  * @param name Name of the bridge object
56  */
57 #define ETH_BRIDGE_INIT(name) \
58 	STRUCT_SECTION_ITERABLE(eth_bridge, name) = \
59 		ETH_BRIDGE_INITIALIZER(name)
60 
61 /** @cond INTERNAL_HIDDEN */
62 
63 struct eth_bridge_iface_context {
64 	sys_snode_t node;
65 	struct eth_bridge *instance;
66 	bool allow_tx;
67 };
68 
69 struct eth_bridge_listener {
70 	sys_snode_t node;
71 	struct k_fifo pkt_queue;
72 };
73 
74 /** @endcond */
75 
76 /**
77  * @brief Add an Ethernet network interface to a bridge
78  *
79  * This adds a network interface to a bridge. The interface is then put
80  * into promiscuous mode, all packets received by this interface are sent
81  * to the bridge, and any other packets sent to the bridge (with some
82  * exceptions) are transmitted via this interface.
83  *
84  * For transmission from the bridge to occur via this interface, it is
85  * necessary to enable TX mode with eth_bridge_iface_tx(). TX mode is
86  * initially disabled.
87  *
88  * Once an interface is added to a bridge, all its incoming traffic is
89  * diverted to the bridge. However, packets sent out with net_if_queue_tx()
90  * via this interface are not subjected to the bridge.
91  *
92  * @param br A pointer to an initialized bridge object
93  * @param iface Interface to add
94  *
95  * @return 0 if OK, negative error code otherwise.
96  */
97 int eth_bridge_iface_add(struct eth_bridge *br, struct net_if *iface);
98 
99 /**
100  * @brief Remove an Ethernet network interface from a bridge
101  *
102  * @param br A pointer to an initialized bridge object
103  * @param iface Interface to remove
104  *
105  * @return 0 if OK, negative error code otherwise.
106  */
107 int eth_bridge_iface_remove(struct eth_bridge *br, struct net_if *iface);
108 
109 /**
110  * @brief Enable/disable transmission mode for a bridged interface
111  *
112  * When TX mode is off, the interface may receive packets and send them to
113  * the bridge but no packets coming from the bridge will be sent through this
114  * interface. When TX mode is on, both incoming and outgoing packets are
115  * allowed.
116  *
117  * @param iface Interface to configure
118  * @param allow true to activate TX mode, false otherwise
119  *
120  * @return 0 if OK, negative error code otherwise.
121  */
122 int eth_bridge_iface_allow_tx(struct net_if *iface, bool allow);
123 
124 /**
125  * @brief Add (register) a listener to the bridge
126  *
127  * This lets a software listener register a pointer to a provided FIFO for
128  * receiving packets sent to the bridge. The listener is responsible for
129  * emptying the FIFO with k_fifo_get() which will return a struct net_pkt
130  * pointer, and releasing the packet with net_pkt_unref() when done with it.
131  *
132  * The listener wishing not to receive any more packets should simply
133  * unregister itself with eth_bridge_listener_remove().
134  *
135  * @param br A pointer to an initialized bridge object
136  * @param l A pointer to an initialized listener instance.
137  *
138  * @return 0 if OK, negative error code otherwise.
139  */
140 int eth_bridge_listener_add(struct eth_bridge *br, struct eth_bridge_listener *l);
141 
142 /**
143  * @brief Remove (unregister) a listener from the bridge
144  *
145  * @param br A pointer to an initialized bridge object
146  * @param l A pointer to the listener instance to be removed.
147  *
148  * @return 0 if OK, negative error code otherwise.
149  */
150 int eth_bridge_listener_remove(struct eth_bridge *br, struct eth_bridge_listener *l);
151 
152 /**
153  * @brief Get bridge index according to pointer
154  *
155  * @param br Pointer to bridge instance
156  *
157  * @return Bridge index
158  */
159 int eth_bridge_get_index(struct eth_bridge *br);
160 
161 /**
162  * @brief Get bridge instance according to index
163  *
164  * @param index Bridge instance index
165  *
166  * @return Pointer to bridge instance or NULL if not found.
167  */
168 struct eth_bridge *eth_bridge_get_by_index(int index);
169 
170 /**
171  * @typedef eth_bridge_cb_t
172  * @brief Callback used while iterating over bridge instances
173  *
174  * @param br Pointer to bridge instance
175  * @param user_data User supplied data
176  */
177 typedef void (*eth_bridge_cb_t)(struct eth_bridge *br, void *user_data);
178 
179 /**
180  * @brief Go through all the bridge instances in order to get
181  *        information about them. This is mainly useful in
182  *        net-shell to print data about currently active bridges.
183  *
184  * @param cb Callback to call for each bridge instance
185  * @param user_data User supplied data
186  */
187 void net_eth_bridge_foreach(eth_bridge_cb_t cb, void *user_data);
188 
189 /**
190  * @}
191  */
192 
193 #ifdef __cplusplus
194 }
195 #endif
196 
197 #endif /* ZEPHYR_INCLUDE_NET_ETHERNET_BRIDGE_H_ */
198