1 /*
2  * Copyright (c) 2021 BayLibre SAS
3  * Copyright (c) 2024 Nordic Semiconductor
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_REGISTER(net_eth_bridge, CONFIG_NET_ETHERNET_BRIDGE_LOG_LEVEL);
10 
11 #include <zephyr/net/net_core.h>
12 #include <zephyr/net/net_l2.h>
13 #include <zephyr/net/net_if.h>
14 #include <zephyr/net/virtual.h>
15 #include <zephyr/net/ethernet.h>
16 #include <zephyr/net/ethernet_bridge.h>
17 #include <zephyr/sys/slist.h>
18 #include <zephyr/random/random.h>
19 
20 #include "net_private.h"
21 #include "bridge.h"
22 
23 #if defined(CONFIG_NET_ETHERNET_BRIDGE_TXRX_DEBUG)
24 #define DEBUG_TX 1
25 #define DEBUG_RX 1
26 #else
27 #define DEBUG_TX 0
28 #define DEBUG_RX 0
29 #endif
30 
31 #define MAX_BRIDGE_NAME_LEN MIN(sizeof("bridge##"), CONFIG_NET_INTERFACE_NAME_LEN)
32 #define MAX_VIRT_NAME_LEN MIN(sizeof("<no config>"), CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN)
33 
lock_bridge(struct eth_bridge_iface_context * ctx)34 static void lock_bridge(struct eth_bridge_iface_context *ctx)
35 {
36 	k_mutex_lock(&ctx->lock, K_FOREVER);
37 }
38 
unlock_bridge(struct eth_bridge_iface_context * ctx)39 static void unlock_bridge(struct eth_bridge_iface_context *ctx)
40 {
41 	k_mutex_unlock(&ctx->lock);
42 }
43 
44 struct ud {
45 	eth_bridge_cb_t cb;
46 	void *user_data;
47 };
48 
iface_cb(struct net_if * iface,void * user_data)49 static void iface_cb(struct net_if *iface, void *user_data)
50 {
51 	struct ud *br_user_data = user_data;
52 	struct eth_bridge_iface_context *ctx;
53 	enum virtual_interface_caps caps;
54 
55 	if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
56 		return;
57 	}
58 
59 	caps = net_virtual_get_iface_capabilities(iface);
60 	if (!(caps & VIRTUAL_INTERFACE_BRIDGE)) {
61 		return;
62 	}
63 
64 	ctx = net_if_get_device(iface)->data;
65 
66 	br_user_data->cb(ctx, br_user_data->user_data);
67 }
68 
net_eth_bridge_foreach(eth_bridge_cb_t cb,void * user_data)69 void net_eth_bridge_foreach(eth_bridge_cb_t cb, void *user_data)
70 {
71 	struct ud br_user_data = {
72 		.cb = cb,
73 		.user_data = user_data,
74 	};
75 
76 	net_if_foreach(iface_cb, &br_user_data);
77 }
78 
eth_bridge_get_index(struct net_if * br)79 int eth_bridge_get_index(struct net_if *br)
80 {
81 	return net_if_get_by_iface(br);
82 }
83 
eth_bridge_get_by_index(int index)84 struct net_if *eth_bridge_get_by_index(int index)
85 {
86 	return net_if_get_by_index(index);
87 }
88 
eth_bridge_iface_add(struct net_if * br,struct net_if * iface)89 int eth_bridge_iface_add(struct net_if *br, struct net_if *iface)
90 {
91 	struct eth_bridge_iface_context *ctx = net_if_get_device(br)->data;
92 	struct ethernet_context *eth_ctx = net_if_l2_data(iface);
93 	bool found = false;
94 	int count = 0;
95 	int ret;
96 
97 	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET) ||
98 	    !(net_eth_get_hw_capabilities(iface) & ETHERNET_PROMISC_MODE)) {
99 		return -EINVAL;
100 	}
101 
102 	if (net_if_l2(br) != &NET_L2_GET_NAME(VIRTUAL) ||
103 	    !(net_virtual_get_iface_capabilities(br) & VIRTUAL_INTERFACE_BRIDGE)) {
104 		return -EINVAL;
105 	}
106 
107 	lock_bridge(ctx);
108 
109 	if (eth_ctx->bridge == br) {
110 		/* This Ethernet interface was already added to the bridge */
111 		found = true;
112 	}
113 
114 	ARRAY_FOR_EACH(ctx->eth_iface, i) {
115 		if (!found && ctx->eth_iface[i] == NULL) {
116 			ctx->eth_iface[i] = iface;
117 			eth_ctx->bridge = br;
118 			found = true;
119 		}
120 
121 		/* Calculate how many interfaces are added to this bridge */
122 		if (ctx->eth_iface[i] != NULL) {
123 			struct ethernet_context *tmp = net_if_l2_data(ctx->eth_iface[i]);
124 
125 			if (tmp->bridge == br) {
126 				count++;
127 			}
128 		}
129 	}
130 
131 	unlock_bridge(ctx);
132 
133 	if (!found) {
134 		return -ENOMEM;
135 	}
136 
137 	ret = net_eth_promisc_mode(iface, true);
138 	if (ret != 0 && ret != -EALREADY) {
139 		/* Ignore any errors when using native-sim driver,
140 		 * we do not need host promiscuous working when testing
141 		 * bridging using native-sim.
142 		 */
143 		if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX)) {
144 			NET_DBG("iface %d promiscuous mode failed: %d",
145 				net_if_get_by_iface(iface), ret);
146 			eth_bridge_iface_remove(br, iface);
147 			return ret;
148 		}
149 	}
150 
151 	NET_DBG("iface %d added to bridge %d", net_if_get_by_iface(iface),
152 		net_if_get_by_iface(br));
153 
154 	if (count > 1) {
155 		ctx->is_setup = true;
156 
157 		NET_INFO("Bridge %d is %ssetup", net_if_get_by_iface(eth_ctx->bridge), "");
158 
159 		net_virtual_set_name(ctx->iface, "<config ok>");
160 	}
161 
162 	ctx->count = count;
163 
164 	return 0;
165 }
166 
eth_bridge_iface_remove(struct net_if * br,struct net_if * iface)167 int eth_bridge_iface_remove(struct net_if *br, struct net_if *iface)
168 {
169 	struct eth_bridge_iface_context *ctx = net_if_get_device(br)->data;
170 	struct ethernet_context *eth_ctx = net_if_l2_data(iface);
171 	bool found = false;
172 	int count = 0;
173 
174 	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
175 		return -EINVAL;
176 	}
177 
178 	if (net_if_l2(br) != &NET_L2_GET_NAME(VIRTUAL) ||
179 	    !(net_virtual_get_iface_capabilities(br) & VIRTUAL_INTERFACE_BRIDGE)) {
180 		return -EINVAL;
181 	}
182 
183 	lock_bridge(ctx);
184 
185 	ARRAY_FOR_EACH(ctx->eth_iface, i) {
186 		if (!found && ctx->eth_iface[i] == iface) {
187 			ctx->eth_iface[i] = NULL;
188 			eth_ctx->bridge = NULL;
189 			found = true;
190 		}
191 
192 		/* Calculate how many interfaces are added to this bridge */
193 		if (ctx->eth_iface[i] != NULL) {
194 			struct ethernet_context *tmp = net_if_l2_data(ctx->eth_iface[i]);
195 
196 			if (tmp->bridge == br) {
197 				count++;
198 			}
199 		}
200 	}
201 
202 	unlock_bridge(ctx);
203 
204 	NET_DBG("iface %d removed from bridge %d", net_if_get_by_iface(iface),
205 		net_if_get_by_iface(br));
206 
207 	if (count < 2) {
208 		ctx->is_setup = false;
209 
210 		NET_INFO("Bridge %d is %ssetup", net_if_get_by_iface(br), "not ");
211 
212 		net_virtual_set_name(ctx->iface, "<no config>");
213 	}
214 
215 	ctx->count = count;
216 
217 	return 0;
218 }
219 
is_link_local_addr(struct net_eth_addr * addr)220 static inline bool is_link_local_addr(struct net_eth_addr *addr)
221 {
222 	if (addr->addr[0] == 0x01 &&
223 	    addr->addr[1] == 0x80 &&
224 	    addr->addr[2] == 0xc2 &&
225 	    addr->addr[3] == 0x00 &&
226 	    addr->addr[4] == 0x00 &&
227 	    (addr->addr[5] & 0x0f) == 0x00) {
228 		return true;
229 	}
230 
231 	return false;
232 }
233 
random_linkaddr(uint8_t * linkaddr,size_t len)234 static void random_linkaddr(uint8_t *linkaddr, size_t len)
235 {
236 	sys_rand_get(linkaddr, len);
237 }
238 
bridge_iface_init(struct net_if * iface)239 static void bridge_iface_init(struct net_if *iface)
240 {
241 	struct eth_bridge_iface_context *ctx = net_if_get_device(iface)->data;
242 	struct virtual_interface_context *vctx = net_if_l2_data(iface);
243 	char name[MAX_BRIDGE_NAME_LEN];
244 
245 	if (ctx->is_init) {
246 		return;
247 	}
248 
249 	k_mutex_init(&ctx->lock);
250 
251 	ctx->iface = iface;
252 
253 	net_if_flag_set(iface, NET_IF_NO_AUTO_START);
254 	net_if_flag_clear(iface, NET_IF_IPV4);
255 	net_if_flag_clear(iface, NET_IF_IPV6);
256 	net_if_flag_clear(iface, NET_IF_FORWARD_MULTICASTS);
257 
258 	net_virtual_set_flags(iface, NET_L2_PROMISC_MODE);
259 
260 	snprintk(name, sizeof(name), "bridge%d", ctx->id);
261 	net_if_set_name(iface, name);
262 
263 	net_virtual_set_name(iface, "<no config>");
264 
265 	/* We need to set the link address here as normally it would be set in
266 	 * virtual interface API attach function but we do not use that in
267 	 * bridging.
268 	 */
269 	random_linkaddr(vctx->lladdr.addr, sizeof(vctx->lladdr.addr));
270 
271 	vctx->lladdr.len = sizeof(vctx->lladdr.addr);
272 	vctx->lladdr.type = NET_LINK_UNKNOWN;
273 
274 	net_if_set_link_addr(iface, vctx->lladdr.addr,
275 			     vctx->lladdr.len, vctx->lladdr.type);
276 
277 	ctx->is_init = true;
278 	ctx->is_setup = false;
279 }
280 
bridge_get_capabilities(struct net_if * iface)281 static enum virtual_interface_caps bridge_get_capabilities(struct net_if *iface)
282 {
283 	ARG_UNUSED(iface);
284 
285 	return VIRTUAL_INTERFACE_BRIDGE;
286 }
287 
bridge_iface_start(const struct device * dev)288 static int bridge_iface_start(const struct device *dev)
289 {
290 	struct eth_bridge_iface_context *ctx = dev->data;
291 
292 	if (!ctx->is_setup) {
293 		NET_DBG("Bridge interface %d not configured yet.",
294 			net_if_get_by_iface(ctx->iface));
295 		return -ENOENT;
296 	}
297 
298 	if (ctx->status) {
299 		return -EALREADY;
300 	}
301 
302 	ctx->status = true;
303 
304 	NET_DBG("Starting iface %d", net_if_get_by_iface(ctx->iface));
305 
306 	NET_INFO("Bridge %d is %sactive", net_if_get_by_iface(ctx->iface), "");
307 
308 	net_virtual_set_name(ctx->iface, "<enabled>");
309 
310 	return 0;
311 }
312 
bridge_iface_stop(const struct device * dev)313 static int bridge_iface_stop(const struct device *dev)
314 {
315 	struct eth_bridge_iface_context *ctx = dev->data;
316 
317 	if (!ctx->status) {
318 		return -EALREADY;
319 	}
320 
321 	ctx->status = false;
322 
323 	NET_DBG("Stopping iface %d", net_if_get_by_iface(ctx->iface));
324 
325 	NET_INFO("Bridge %d is %sactive", net_if_get_by_iface(ctx->iface), "not ");
326 
327 	if (ctx->is_setup) {
328 		net_virtual_set_name(ctx->iface, "<disabled>");
329 	} else {
330 		net_virtual_set_name(ctx->iface, "<no config>");
331 	}
332 
333 	return 0;
334 }
335 
bridge_iface_process(struct net_if * iface,struct net_pkt * pkt,bool is_send)336 static enum net_verdict bridge_iface_process(struct net_if *iface,
337 					     struct net_pkt *pkt,
338 					     bool is_send)
339 {
340 	struct eth_bridge_iface_context *ctx = net_if_get_device(iface)->data;
341 	struct net_if *orig_iface;
342 	struct net_pkt *send_pkt;
343 	size_t count;
344 
345 	/* Drop all link-local packets for now. */
346 	if (is_link_local_addr((struct net_eth_addr *)net_pkt_lladdr_dst(pkt))) {
347 		NET_DBG("DROP: lladdr");
348 		goto out;
349 	}
350 
351 	lock_bridge(ctx);
352 
353 	/* Keep the original packet interface so that we can send to each
354 	 * bridged interface.
355 	 */
356 	orig_iface = net_pkt_orig_iface(pkt);
357 
358 	count = ctx->count;
359 
360 	/* Pass the data to all the Ethernet interface except the originator
361 	 * Ethernet interface.
362 	 */
363 	ARRAY_FOR_EACH(ctx->eth_iface, i) {
364 		if (ctx->eth_iface[i] != NULL && ctx->eth_iface[i] != orig_iface) {
365 			/* Skip it if not up */
366 			if (!net_if_flag_is_set(ctx->eth_iface[i], NET_IF_UP)) {
367 				continue;
368 			}
369 
370 			/* Clone the packet if we have more than two interfaces in the bridge
371 			 * because the first send might mess the data part of the message.
372 			 */
373 			if (count > 2) {
374 				send_pkt = net_pkt_clone(pkt, K_NO_WAIT);
375 				if (send_pkt == NULL) {
376 					NET_DBG("DROP: clone failed");
377 					break;
378 				}
379 
380 				net_pkt_ref(send_pkt);
381 			} else {
382 				send_pkt = net_pkt_ref(pkt);
383 			}
384 
385 			net_pkt_set_family(send_pkt, AF_UNSPEC);
386 			net_pkt_set_iface(send_pkt, ctx->eth_iface[i]);
387 			net_if_queue_tx(ctx->eth_iface[i], send_pkt);
388 
389 			NET_DBG("%s iface %d pkt %p (ref %d)",
390 				is_send ? "Send" : "Recv",
391 				net_if_get_by_iface(ctx->eth_iface[i]),
392 				send_pkt, (int)atomic_get(&send_pkt->atomic_ref));
393 
394 			net_pkt_unref(send_pkt);
395 		}
396 	}
397 
398 	unlock_bridge(ctx);
399 
400 out:
401 	/* The packet was cloned by the caller so remove it here. */
402 	net_pkt_unref(pkt);
403 
404 	return NET_OK;
405 }
406 
bridge_iface_send(struct net_if * iface,struct net_pkt * pkt)407 int bridge_iface_send(struct net_if *iface, struct net_pkt *pkt)
408 {
409 	if (DEBUG_TX) {
410 		char str[sizeof("TX iface xx")];
411 
412 		snprintk(str, sizeof(str), "TX iface %d",
413 			 net_if_get_by_iface(net_pkt_iface(pkt)));
414 
415 		net_pkt_hexdump(pkt, str);
416 	}
417 
418 	(void)bridge_iface_process(iface, pkt, true);
419 
420 	return 0;
421 }
422 
bridge_iface_recv(struct net_if * iface,struct net_pkt * pkt)423 static enum net_verdict bridge_iface_recv(struct net_if *iface,
424 					  struct net_pkt *pkt)
425 {
426 	if (DEBUG_RX) {
427 		char str[sizeof("RX iface xx")];
428 
429 		snprintk(str, sizeof(str), "RX iface %d",
430 			 net_if_get_by_iface(net_pkt_iface(pkt)));
431 
432 		net_pkt_hexdump(pkt, str);
433 	}
434 
435 	return bridge_iface_process(iface, pkt, false);
436 }
437 
438 /* We cannot attach the bridge interface to Ethernet interface because
439  * the attachment can be done to only one Ethernet interface and we
440  * need to "attach" at least two Ethernet interfaces to the bridge interface.
441  * So we return -ENOTSUP here so that the attachment fails if it is tried.
442  */
bridge_iface_attach(struct net_if * br,struct net_if * iface)443 static int bridge_iface_attach(struct net_if *br,
444 			       struct net_if *iface)
445 {
446 	ARG_UNUSED(br);
447 	ARG_UNUSED(iface);
448 
449 	return -ENOTSUP;
450 }
451 
452 static const struct virtual_interface_api bridge_iface_api = {
453 	.iface_api.init = bridge_iface_init,
454 
455 	.get_capabilities = bridge_get_capabilities,
456 	.start = bridge_iface_start,
457 	.stop = bridge_iface_stop,
458 	.send = bridge_iface_send,
459 	.recv = bridge_iface_recv,
460 	.attach = bridge_iface_attach,
461 };
462 
463 #define ETH_DEFINE_BRIDGE(x, _)						\
464 	static struct eth_bridge_iface_context bridge_context_data_##x = { \
465 		.id = x,						\
466 	};								\
467 	NET_VIRTUAL_INTERFACE_INIT_INSTANCE(bridge_##x,			\
468 					    "BRIDGE_" #x,		\
469 					    x,				\
470 					    NULL,			\
471 					    NULL,			\
472 					    &bridge_context_data_##x,	\
473 					    NULL, /* config */		\
474 					    CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
475 					    &bridge_iface_api,		\
476 					    NET_ETH_MTU)
477 
478 LISTIFY(CONFIG_NET_ETHERNET_BRIDGE_COUNT, ETH_DEFINE_BRIDGE, (;), _);
479