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