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