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