Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: ethernet: Align handling of different ethernet protocols in recv #83967

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 53 additions & 58 deletions subsys/net/l2/ethernet/ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,57 @@ static void ethernet_mcast_monitor_cb(struct net_if *iface, const struct net_add
}
#endif

static enum net_verdict ethernet_protocol_input(uint16_t type,
struct net_if *iface,
struct net_pkt *pkt)
{
struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);

switch (type) {
case NET_ETH_PTYPE_EAPOL:
return NET_CONTINUE;
case NET_ETH_PTYPE_IP:
net_pkt_set_family(pkt, AF_INET);
return NET_CONTINUE;
case NET_ETH_PTYPE_IPV6:
net_pkt_set_family(pkt, AF_INET6);
return NET_CONTINUE;
#if defined(CONFIG_NET_ARP)
case NET_ETH_PTYPE_ARP:
net_pkt_set_family(pkt, AF_INET);
NET_DBG("ARP packet from %s received",
net_sprint_ll_addr((uint8_t *)hdr->src.addr,
sizeof(struct net_eth_addr)));

if (IS_ENABLED(CONFIG_NET_IPV4_ACD) &&
net_ipv4_acd_input(iface, pkt) == NET_DROP) {
return NET_DROP;
}

return net_arp_input(pkt, hdr);
#endif
#if defined(CONFIG_NET_L2_PTP)
#if defined(CONFIG_NET_GPTP)
case NET_ETH_PTYPE_PTP:
return net_gptp_recv(iface, pkt);
#endif
#endif
#if defined(CONFIG_NET_LLDP)
case NET_ETH_PTYPE_LLDP:
return net_lldp_recv(iface, pkt);
#endif
default:
if (IS_ENABLED(CONFIG_NET_ETHERNET_FORWARD_UNRECOGNISED_ETHERTYPE)) {
return NET_CONTINUE;
}

NET_DBG("Unknown hdr type 0x%04x iface %d (%p)", type,
net_if_get_by_iface(iface), iface);
eth_stats_update_unknown_protocol(iface);
return NET_DROP;
}
}

static enum net_verdict ethernet_recv(struct net_if *iface,
struct net_pkt *pkt)
{
Expand All @@ -240,7 +291,6 @@ static enum net_verdict ethernet_recv(struct net_if *iface,
uint8_t hdr_len = sizeof(struct net_eth_hdr);
uint16_t type;
struct net_linkaddr *lladdr;
sa_family_t family = AF_UNSPEC;
bool is_vlan_pkt = false;

/* This expects that the Ethernet header is in the first net_buf
Expand Down Expand Up @@ -311,44 +361,6 @@ static enum net_verdict ethernet_recv(struct net_if *iface,
}
}

switch (type) {
case NET_ETH_PTYPE_IP:
case NET_ETH_PTYPE_ARP:
net_pkt_set_family(pkt, AF_INET);
family = AF_INET;
break;
case NET_ETH_PTYPE_IPV6:
net_pkt_set_family(pkt, AF_INET6);
family = AF_INET6;
break;
case NET_ETH_PTYPE_EAPOL:
family = AF_UNSPEC;
break;
#if defined(CONFIG_NET_L2_PTP)
case NET_ETH_PTYPE_PTP:
family = AF_UNSPEC;
break;
#endif
case NET_ETH_PTYPE_LLDP:
#if defined(CONFIG_NET_LLDP)
net_buf_pull(pkt->frags, hdr_len);
return net_lldp_recv(iface, pkt);
#else
NET_DBG("LLDP Rx agent not enabled");
goto drop;
#endif
default:
if (IS_ENABLED(CONFIG_NET_ETHERNET_FORWARD_UNRECOGNISED_ETHERTYPE)) {
family = AF_UNSPEC;
break;
}

NET_DBG("Unknown hdr type 0x%04x iface %d (%p)", type,
net_if_get_by_iface(iface), iface);
eth_stats_update_unknown_protocol(iface);
return NET_DROP;
}

/* Set the pointers to ll src and dst addresses */
lladdr = net_pkt_lladdr_src(pkt);
lladdr->addr = hdr->src.addr;
Expand Down Expand Up @@ -398,29 +410,12 @@ static enum net_verdict ethernet_recv(struct net_if *iface,

ethernet_update_rx_stats(iface, hdr, net_pkt_get_len(pkt) + hdr_len);

if (IS_ENABLED(CONFIG_NET_ARP) &&
family == AF_INET && type == NET_ETH_PTYPE_ARP) {
NET_DBG("ARP packet from %s received",
net_sprint_ll_addr((uint8_t *)hdr->src.addr,
sizeof(struct net_eth_addr)));

if (IS_ENABLED(CONFIG_NET_IPV4_ACD) &&
net_ipv4_acd_input(iface, pkt) == NET_DROP) {
return NET_DROP;
}

return net_arp_input(pkt, hdr);
}

if (IS_ENABLED(CONFIG_NET_GPTP) && type == NET_ETH_PTYPE_PTP) {
return net_gptp_recv(iface, pkt);
}

if (type != NET_ETH_PTYPE_EAPOL) {
ethernet_update_length(iface, pkt);
}

return NET_CONTINUE;
return ethernet_protocol_input(type, iface, pkt);

drop:
eth_stats_update_errors_rx(iface);
return NET_DROP;
Expand Down
Loading