1 /*
2  * SPDX-FileCopyrightText: Copyright 2025 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_bridge_sample, CONFIG_NET_L2_ETHERNET_LOG_LEVEL);
9 
10 #include <zephyr/net/ethernet_bridge.h>
11 
12 struct ud {
13 	struct net_if *bridge;
14 	struct net_if *iface[CONFIG_NET_ETHERNET_BRIDGE_ETH_INTERFACE_COUNT];
15 #if defined(CONFIG_NET_MGMT_EVENT) && defined(CONFIG_NET_DHCPV4)
16 	struct net_mgmt_event_callback mgmt_cb;
17 #endif
18 };
19 
20 struct ud g_user_data = {0};
21 
bridge_find_cb(struct eth_bridge_iface_context * br,void * user_data)22 static void bridge_find_cb(struct eth_bridge_iface_context *br, void *user_data)
23 {
24 	struct ud *u = user_data;
25 
26 	if (u->bridge == NULL) {
27 		u->bridge = br->iface;
28 		LOG_INF("Find bridge iface %d.", net_if_get_by_iface(br->iface));
29 	}
30 }
31 
bridge_add_iface_cb(struct net_if * iface,void * user_data)32 static void bridge_add_iface_cb(struct net_if *iface, void *user_data)
33 {
34 #if defined(CONFIG_NET_DSA) && !defined(CONFIG_NET_DSA_DEPRECATED)
35 	struct ethernet_context *eth_ctx;
36 #endif
37 	struct ud *u = user_data;
38 	int i;
39 
40 	for (i = 0; i < CONFIG_NET_ETHERNET_BRIDGE_ETH_INTERFACE_COUNT; i++) {
41 		if (u->iface[i] == NULL) {
42 			break;
43 		}
44 	}
45 
46 	if (i == CONFIG_NET_ETHERNET_BRIDGE_ETH_INTERFACE_COUNT) {
47 		return;
48 	}
49 
50 	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
51 		return;
52 	}
53 
54 #if defined(CONFIG_NET_DSA) && !defined(CONFIG_NET_DSA_DEPRECATED)
55 	eth_ctx = net_if_l2_data(iface);
56 
57 	if (eth_ctx->dsa_port == DSA_USER_PORT || eth_ctx->dsa_port == NON_DSA_PORT) {
58 		u->iface[i] = iface;
59 	}
60 #else
61 	u->iface[i] = iface;
62 #endif
63 	eth_bridge_iface_add(u->bridge, iface);
64 	LOG_INF("Find iface %d. Add into bridge.", net_if_get_by_iface(iface));
65 }
66 
67 #if defined(CONFIG_NET_MGMT_EVENT) && defined(CONFIG_NET_DHCPV4)
event_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)68 static void event_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
69 			  struct net_if *iface)
70 {
71 	struct ethernet_context *eth_ctx;
72 
73 	ARG_UNUSED(cb);
74 
75 	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
76 		return;
77 	}
78 
79 	eth_ctx = net_if_l2_data(iface);
80 
81 	if (net_eth_iface_is_bridged(eth_ctx) && mgmt_event == NET_EVENT_IF_UP) {
82 		net_dhcpv4_restart(net_eth_get_bridge(eth_ctx));
83 		return;
84 	}
85 }
86 #endif
87 
main(void)88 int main(void)
89 {
90 	struct ud *u = &g_user_data;
91 
92 	net_eth_bridge_foreach(bridge_find_cb, u);
93 	net_if_foreach(bridge_add_iface_cb, u);
94 	net_if_up(u->bridge);
95 #if defined(CONFIG_NET_MGMT_EVENT) && defined(CONFIG_NET_DHCPV4)
96 	net_mgmt_init_event_callback(&u->mgmt_cb, event_handler, NET_EVENT_IF_UP);
97 	net_mgmt_add_event_callback(&u->mgmt_cb);
98 #endif
99 	return 0;
100 }
101