net: ethernet: bridging support

This adds the ability to create Ethernet bridges for connecting
separate Ethernet segments together to appear as a single
Ethernet network.

This mimics the Linux functionality of the same name.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2021-06-25 18:54:17 -04:00 committed by Christopher Friedt
commit 89482f0119
11 changed files with 519 additions and 3 deletions

View file

@ -30,6 +30,7 @@ LOG_MODULE_REGISTER(net_ethernet, CONFIG_NET_L2_ETHERNET_LOG_LEVEL);
#include "net_private.h"
#include "ipv6.h"
#include "ipv4_autoconf_internal.h"
#include "bridge.h"
#define NET_BUF_TIMEOUT K_MSEC(100)
@ -187,6 +188,19 @@ static enum net_verdict ethernet_recv(struct net_if *iface,
goto drop;
}
if (IS_ENABLED(CONFIG_NET_ETHERNET_BRIDGE) &&
net_eth_iface_is_bridged(ctx)) {
net_pkt_set_l2_bridged(pkt, true);
net_pkt_lladdr_src(pkt)->addr = hdr->src.addr;
net_pkt_lladdr_src(pkt)->len = sizeof(struct net_eth_addr);
net_pkt_lladdr_src(pkt)->type = NET_LINK_ETHERNET;
net_pkt_lladdr_dst(pkt)->addr = hdr->dst.addr;
net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
net_pkt_lladdr_dst(pkt)->type = NET_LINK_ETHERNET;
ethernet_update_rx_stats(iface, pkt, net_pkt_get_len(pkt));
return net_eth_bridge_input(ctx, pkt);
}
type = ntohs(hdr->type);
if (net_eth_is_vlan_enabled(ctx, iface) &&
@ -578,7 +592,19 @@ static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)
goto error;
}
if (IS_ENABLED(CONFIG_NET_IPV4) &&
if (IS_ENABLED(CONFIG_NET_ETHERNET_BRIDGE) &&
net_pkt_is_l2_bridged(pkt)) {
net_pkt_cursor_init(pkt);
ret = net_l2_send(api->send, net_if_get_device(iface), iface, pkt);
if (ret != 0) {
eth_stats_update_errors_tx(iface);
goto error;
}
ethernet_update_tx_stats(iface, pkt);
ret = net_pkt_get_len(pkt);
net_pkt_unref(pkt);
return ret;
} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
net_pkt_family(pkt) == AF_INET) {
struct net_pkt *tmp;