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