3ethernet_frame ethernet_frame::parse_ethernet(nonstd::span<const std::uint8_t> frame) {
7 throw std::runtime_error(
"frame too small for Ethernet header");
11 std::uint16_t t = bswap16(eth_frame.l2.type_or_len);
16 auto is_vlan_tpid = [](std::uint16_t x) {
return x == 0x8100 || x == 0x88A8; };
20 throw std::runtime_error(
"frame too small for VLAN tag");
23 std::memcpy(&tag, frame.data() + offset,
sizeof(tag));
24 eth_frame.has_vlan =
true;
25 eth_frame.vlan_tpid = t;
27 std::uint16_t tci = bswap16(tag.tci);
28 eth_frame.vlan_pcp = (tci >> 13) & 0x7;
29 eth_frame.vlan_dei = ((tci >> 12) & 0x1) != 0;
30 eth_frame.vlan_id = tci & 0x0FFF;
35 std::uint16_t inner{};
36 std::memcpy(&inner, frame.data() + offset,
sizeof(inner));
38 offset +=
sizeof(inner);
44 eth_frame.kind = ether_kind::LENGTH_8023;
45 eth_frame.etherType_or_len = t;
47 eth_frame.kind = ether_kind::ETHER_TYPE;
48 eth_frame.etherType_or_len = t;
51 if(frame.size() < offset)
52 throw std::runtime_error(
"internal parse error (offset beyond frame)");
54 eth_frame.payload = frame.subspan(offset);