Skip to content

Don't fail on unsupported DSA tag #1451

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

vladimiroltean
Copy link

Up until commit 8f1f6fc ("If we can't allocate a DLT_ list, fail."), the iface_dsa_get_proto_info() return code was ignored, but now it isn't.

Many DSA tags are in use which libpcap has no idea about: #1367

Let's keep the behavior as before, i.e. don't give up on these packets, even though we don't know what's inside.

Up until commit 8f1f6fc ("If we can't allocate a DLT_ list,
fail."), the iface_dsa_get_proto_info() return code was ignored, but now
it isn't.

Many DSA tags are in use which libpcap has no idea about:
the-tcpdump-group#1367

Let's keep the behavior as before, i.e. don't give up on these packets,
even though we don't know what's inside.
@minimaxwell
Copy link

Hello Vlad,

I'm all in for that one, I gave it a test and it works fine (debugging a ksz9477 setup whose tag format isn't supported as well). I strongly agree that this regression needs fixing.

Thanks,

Maxime

@guyharris
Copy link
Member

So what will handle->linktype be set to in this case? DLT_EN10MB?

@vladimiroltean
Copy link
Author

Yeah. I mean, they look horrible in tcpdump, but it gets the job done.

root@debian:~# tcpdump -i end0 -e -n -XX
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on end0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
00:20:19.523547 d8:58:d7:00:ca:6d > 01:80:c2:02:00:00, ethertype Unknown (0xdadb), length 64: 
        0x0000:  0180 c202 0000 d858 d700 ca6d dadb 0c02  .......X...m....
        0x0010:  0027 4242 0300 0002 023e 7fff c87f 54df  .'BB.....>....T.
        0x0020:  a740 0000 4e20 8000 9632 d9a4 8e67 8002  .@..N....2...g..
        0x0030:  0100 0a00 0200 0800 0000 0000 0000 0000  ................

@infrastation
Copy link
Member

So these packets are not actually Ethernet, correct?

@vladimiroltean
Copy link
Author

They are absolutely Ethernet frames with an extra header (generically called "tag" because depending on switch vendor, it may not actually be "header" but also "trailer") that contains switch-specific information. For example, in the dump above, if you remove "dadb 0c02", what you get is a normal STP packet.
Actually DSA is the layer in the kernel which decodes this switch tag and creates virtual interfaces (stacked on top of the physical one, similar to VLAN) for each switch port (a field in this tag). If you run tcpdump on the virtual switch interfaces, it's normal Ethernet with all that entails - they're Ethernet switches. If you run tcpdump on the physical host interface you get this gibberish.
See page 5 of https://netdevconf.info/2.1/papers/distributed-switch-architecture.pdf.

@infrastation
Copy link
Member

Thank you for the comments. Do you mean in this specific case it is exactly one of those or something else?

@vladimiroltean
Copy link
Author

No, it's not one of the 4 protocols for which libpcap assigns a specific link type, but rather one of the remaining 25 for which it doesn't.
https://elixir.bootlin.com/linux/v6.13.2/source/include/net/dsa.h#L58
Mostly nobody bothers to write decoders for these, and would rather spend a few more minutes to look at a raw hex dump of the packet with no pretty printing, in the off occasion that debugging at this level is actually necessary at all.
The blamed patch actually made debugging impossible for the vast majority of DSA protocols.

@guyharris
Copy link
Member

guyharris commented Feb 13, 2025

No, it's not one of the 4 protocols for which libpcap assigns a specific link type, but rather one of the remaining 25 for which it doesn't.

Then perhaps we should assign more of them, and do tcpdump and Wireshark dissectors for them.

Mostly nobody bothers to write decoders for these, and would rather spend a few more minutes to look at a raw hex dump of the packet with no pretty printing, in the off occasion that debugging at this level is actually necessary at all.

Then it sounds as if there should be a LINKTYPE_DSA_UNSUPPORTED type, which is dissected as a raw hex dump by tcpdump/Wireshark/etc., rather than using LINKTYPE_ETHERNET and dissecting those as Ethernet.

@vladimiroltean
Copy link
Author

I mean, they are Ethernet packets, and comply to all Ethernet packet rules. The host port (which is most of the time a regular, DSA-unaware network card, and which any other day would actually use DLT_EN10M) parses as much of the packet as it can, and it treats it for what it is - an Ethernet frame with an unknown Ethertype. In the example above, "d8:58:d7:00:ca:6d > 01:80:c2:02:00:00, ethertype Unknown (0xdadb), length 64" is exactly as much as the protocol parser of the host port makes out of this packet. I don't know to what end we would lose even this small amount of information by dissecting as a raw hex dump in favor of just falling back to DLT_EN10M.

@guyharris
Copy link
Member

guyharris commented Feb 14, 2025

I mean, they are Ethernet packets, and comply to all Ethernet packet rules.

By which you presumably mean "they are blobs of bytes that, somewhere within them, contain an Ethernet packet, perhaps with additional stuff stuck in front of it, after it, or in the middle of it."

See, for example, the LINKTYPE_DSA_TAG_BRCM_PREPEND type, in which the tag appears before the destination address; the DSA tag doesn't look as if it's inserted the way a VLAN tag is.

So, no, an Ethernet dissector will not necessarily...

The host port (which is most of the time a regular, DSA-unaware network card, and which any other day would actually use DLT_EN10M) parses as much of the packet as it can, and it treats it for what it is - an Ethernet frame with an unknown Ethertype.

...parse the packet as being an Ethernet frame with an unknown Ethertype. If LINKTYPE_DSA_TAG_BRCM_PREPEND is the ONLY tag type that's a prefix rather than either a trailer or something inserted in the fashion of a VLAN tag - i.e., its first two octets are an Ethertype that's been assigned so that it won't be used by anything other than the DSA tag in question - then, yes, it can be made to work with LINKTYPE_ETHERNET.

And if, in fact, that's the case, then we don't need LINKTYPE_DSA_TAG_xxx types for anything other than prepend or trailer types, as tcpdump, Wireshark, etc. can just use the Ethertype value to determine the DSA tag type.

However, if a DSA tag type is ever used for on-the-wire Ethernet traffic, a LINKTYPE_ value is needed. I think there might be places where it is, but maybe I'm thinking of something else.

In the example above, "d8:58:d7:00:ca:6d > 01:80:c2:02:00:00, ethertype Unknown (0xdadb), length 64" is exactly as much as the protocol parser of the host port makes out of this packet. I don't know to what end we would lose even this small amount of information by dissecting as a raw hex dump in favor of just falling back to DLT_EN10M.

@infrastation
Copy link
Member

Arguably, if the frame was Ethernet, the hardware and the kernel would both handle it as Ethernet. If they both handle it as DSA, then most likely it is DSA. It would be most helpful to focus on the specification.

@guyharris
Copy link
Member

Arguably, if the frame was Ethernet, the hardware and the kernel would both handle it as Ethernet. If they both handle it as DSA, then most likely it is DSA. It would be most helpful to focus on the specification.

Which specification? DSA doesn't specify what tags look like - that's up to the vendor, and many of them seem to do their own thing.

@vladimiroltean
Copy link
Author

vladimiroltean commented Feb 14, 2025

So when I said that the host port is "most of the time a regular, DSA-unaware network card", I really selected my words carefully by saying "most of the time", and I wasn't trying to be dishonest about omitting the rest, it's just that I consider the exceptions to be irrelevant to this discussion. However you decided to pick out LINKTYPE_DSA_TAG_BRCM_PREPEND, which is one of the exceptions.

By which you presumably mean "they are blobs of bytes that, somewhere within them, contain an Ethernet packet, perhaps with additional stuff stuck in front of it, after it, or in the middle of it.

Very broadly speaking, DSA switches encapsulate Ethernet frames when delivering them towards the host port, yes, but I don't want you to draw the wrong conclusion from that.
See, many DSA switches are discrete chips, and the switch vendor doesn't control which network card it will be integrated with, on the final PCB. Making sure that packets pass through the host interface's RX filters is a serious concern, so the encapsulation has to be backwards compatible with Ethernet to an acceptable degree. For these reasons, category 2 and 3 tagging protocols, as described here, are popular with discrete chips - although they don't come without their own challenges. Just one example: since individual DSA switch port may have their own MAC address, potentially not equal to the host port's MAC address, the kernel framework has to explicitly manage the RX filtering lists of the host port to not drop these foreign MAC DA values.
Category 1 tagging protocols have a different philosophy. Some designs guarantee they'll bypass the host port's RX filter by using a long prefix as a substitute for the Ethernet header, so that the MAC DA appears as broadcast to the host port, like Ocelot. Note that current the Ocelot tagging protocol in the kernel does not use the long prefix though, but the short one, for reasons that were explained in this commit. Anyway, compatibility with the Ethernet header is always a concern.

But you've jumped straight to LINKTYPE_DSA_TAG_BRCM_PREPEND, and I believe that only now do we have all the context on the table to explain it.

Sometimes, DSA switches are integrated on the same silicon die with an entire SoC, and there you still have an internal Ethernet host port for management traffic. Sometimes, the vendor of the host port IP is different than the vendor of the integrated switch IP, like NXP LS1028A, with an enetc host and an ocelot switch. So, that changes nothing in terms of having to be Ethernet-compatible, because that's still the common denominator even though they're both on the same SoC. But sometimes, an SoC vendor like Broadcom integrates a Broadcom switch with a Broadcom host port, and they have the chance to optimize that integration, and break the compatibility with Ethernet for that internal MAC-to-MAC connection. Because all traffic that the host port is going to see is coming from the switch, these guys can modify the hardware protocol parser of the host port to essentially expect the DSA encapsulation. You can ask yourself why, if they bothered to optimize the design, they didn't go all the way and provide a more performant packet I/O mechanism, like have buffer descriptor rings and DMA for each switch port rather than the bottleneck of a single internal Ethernet link, and the answer has to do with the fact that it's just an evolution of the baseline design I already presented earlier. Anyway, you could make a valid point that DSA tagging protocols that aren't backwards compatible with Ethernet should have a dedicated link type, but that point is moot with LINKTYPE_DSA_TAG_BRCM_PREPEND which already does, but honestly, backwards compatiblity with Ethernet is not something that we as DSA maintainers monitor when we review new tagging protocol submissions, so I can't tell you for sure how many other such protocols are there in the wild. I'll try to think of some way to integrate in the medium term testing of new tagging protocols with the dsa_loop kernel driver (which is a way of making any Ethernet interface think it's attached to a DSA switch even if it physically isn't), and inform patch submitters that it's mandatory for them to submit a dedicated link type to libpcap if the protocol is not backwards-compatible with Ethernet. That's about the most I can promise, but I really want the assumed default to remain that DSA tagging protocols are compatible with Ethernet to some extent. Who wants to add a specific link type for a certain Ethernet-compatible protocol, perfectly fine, but don't force that.

@vladimiroltean
Copy link
Author

And if, in fact, that's the case, then we don't need LINKTYPE_DSA_TAG_xxx types for anything other than prepend or trailer types, as tcpdump, Wireshark, etc. can just use the Ethertype value to determine the DSA tag type.

There are cases which are not as simple as that.
Case 1 - Original Marvell DSA (not EtherType DSA) which is a category 2 protocol but lacks an EtherType. You need to know you're looking at Marvell DSA before understanding what to make of it. Yes, original Marvell DSA is an imperfect design due to the fact that variable fields map over what the host port perceives as EtherType in ways that the host port doesn't like, and there have been instances of that. Yet it exists, and there's nothing we can do about it.
Case 2 - NXP SJA1105 and SJA1110, whose documented tagging protocol is essentially a hybrid of a hardware tagging mechanism and a software-defined tagging mechanism. For link-local L2 multicast, the SJA1105 will patch up bytes of the original MAC DA with the source port and switch ID, in no way increasing the packet size, with the expectation that software recovers these values and patches up those MAC DA bytes back to zeroes. For any other traffic type, the hardware has no assist for source port identification, so the software configures it to send packets as VLAN-tagged towards the host port, with a custom VLAN TPID of 0xdadb, and with the VLAN ID identifying the source port of the packet. That method does increase the packet size. But when looking at the tagging protocol as a whole, not all traffic is identifiable by EtherType, and not even all tagged packets have the same tag length.

Look, I really appreciate that you two are trying to understand and leave no stone unturned, but you have to understand that this regression has a bit of an urgency to it. Even though the change was made a long time ago, it only made it to distributions recently, and it has started affecting people.

@vladimiroltean
Copy link
Author

However, if a DSA tag type is ever used for on-the-wire Ethernet traffic, a LINKTYPE_ value is needed. I think there might be places where it is, but maybe I'm thinking of something else.

You need to define "wire" here. DSA-tagged traffic is passed between the switch and its host port. Since the host port is a dedicated Ethernet interface, that's pretty much "on the wire" as far as it's concerned, but outside of this system, DSA tags are not visible to the outside world. We would really hide the host port from being visible in ifconfig if we could, because as a user you're not supposed to interact with it, but directly with the switch user ports, but we can't, and it's occasionally useful to debug by running tcpdump on it. The host port is just a resource used by DSA, a dumb pipe, and the "wire" varies from Verilog wires (for integrated switches) to PCB traces to regular Ethernet cables (think Beaglebone Black connected to a switch evaluation board).

Though, mainly during developer testing, we can activate the dsa_loop kernel driver, and this lets any Ethernet interface speak a certain DSA tagging protocol with the outside world, with no switch to parse the tags. The public infrastructure for this isn't developed almost at all - anybody who does this has their own tooling for their own purpose. But we treat a DSA tagging protocol, as identified by its textual name, as stable ABI (at least after a certain point, there have been incompatible changes before, which we're trying not to repeat), and anybody who wants to transition a protocol from the Ethernet link type to a specific one can do so at any time in the future.

@guyharris
Copy link
Member

Yes, I'd already read the part of the DSA documentation about the three tag types.

For type 1 tags, such as LINKTYPE_DSA_TAG_BRCM_PREPEND, programs reading those packets will not dissect anything correctly unless it's assigned a LINKTYPE_/DLT_ value separate from LINKTYPE_ETHERNET/DLT_EN10MB, as the frame doesn't begin with a 6-octet destination address, followed by a 6-octet source address, followed by a type/length field, it begins with a tag.

For type 2, if the tag begins with a two-octet big-endian field that contains an assigned Ethertype value that is used only for a particular tag type, then LINKTYPE_ETHERNET/DLT_EN10MB can handle that type - if tcpdump or Wireshark or... handle that Ethertype value, they can dissect the frame correctly, showing the MAC addresses, the tag, and the following Etherype/length and payload. Otherwise, it would need a separate LINKTYPE_/DLT_ in order to dissect the tag and payload.

For type 3, the frame can be dissected as LINKTYPE_ETHERNET/DLT_EN10MB, but will have extra stuff at the end. Assigning a LINKTYPE_/DLT_ value separate from LINKTYPE_ETHERNET/DLT_EN10MB would allow the tag to be dissected, rather than to be treated as part of the packet payload, which might cause it to be misdirected if the payload protocol doesn't have its own length field.

So if somebody can provide a list of the tag types that are:

  • type 1;
  • type 2 with a tag that does not begin with an assigned Ethertype value;
  • type 2 with a tag that begins with an assigned Ethertype value, but where that Ethertype value is not sufficient to determine the packet format;
  • type 3;

then we can assign LINKTYPE_/DLT_ values to those, and use LINKTYPE_ETHERNET/DLT_EN10MB for all the other types. That would mean having the dsa_protos[] table contain only the types from the list, and the code would useLINKTYPE_ETHERNET/DLT_EN10MB for any tag type not fund in that table.

So:

  • "brcm" is type 2 with a tag that does not begin with an assigned Ethertype value;
  • "brcm-prepend" is type 1;
  • "dsa" is type 2 with a tag that does not begin with an assigned Ethertype value;
  • "edsa" is type 2 with a tag that begins with a 2-octet type, but I think that type is programmable, so there's no guarantee that it's not going to be set to a value that means something else for regular Ethernet traffic;
  • "rtl4a" is type 2 with a tag that begins with an assigned Ethertype value, 0x8899, that is also used for Ethernet packets, but where the packet includes a packet type field that allows a dissector to distinguish between various packet formats with that type value;
  • "rtl8_4" is type 2 with a tag that begins with the same Ethertype value, 0x8899;
  • "rtl8_4t" is type 3.

Currently:

  • we have LINKTYPE_/DLT_ values for "brcm", "brcm-prepend", "dsa", and "edsa", which is as it should be, as they're either type 1 or type 2 without a usable Ethertype value;
  • we use LINKTYPE_ETHERNET/DLT_EN10MB for "rtl4a" and "rtl8_4", which is as it probably should be, as they have an assigned Ethertype and the data following the Ethertype has fields that allow distinguishing between different formats (tags and on-the-Ethernet Realtek protocols);
  • we use LINKTYPE_ETHERNET/DLT_EN10MB for "rtl8_4t", which is not as it should be, as it's a trailer tag, but we'd need to write dissectors for them if we assigned it its own LINKTYPE_/DLT_ value, and trailer-protocol dissectors have to be written carefully (so as to properly handle packets sliced with a snapshot length), so we'll leave that it is for now.

I'd be inclined, for now, to fall back on LINKTYPE_ETHERNET/DLT_EN10MB for unknown types, but assign LINKTYPE_/DLT_ values for type 1/type 2 without a usable Ethertype/type 3 tags in the future. It would be nice if there were a way to somehow indicate to the program reading packets that the purported LINKTYPE_ETHERNET/DLT_EN10MB are assigned that LINKTYPE_/DLT_ value as a fallback and that it might not be correct, but the libpcap API and the pcap file format has no way to do that.

It would be very helpful if somebody could provide a list of type 1/type 2 without a usable Ethertype/type 3 tags, so we could, if nothing else, put entries in the dsa_protos[] table that map them to DLT_EN10MB, with a comment noting that they really need their own link-layer type.

@vladimiroltean
Copy link
Author

Currently:
we have LINKTYPE_/DLT_ values for "brcm", "brcm-prepend", "dsa", and "edsa", which is as it should be, as they're either type 1 or type 2 without a usable Ethertype value;
we use LINKTYPE_ETHERNET/DLT_EN10MB for "rtl4a" and "rtl8_4", which is as it probably should be, as they have an assigned Ethertype and the data following the Ethertype has fields that allow distinguishing between different formats (tags and on-the-Ethernet Realtek protocols);

As per your own criteria, you have edsa in the wrong category (it has its own link type but by your logic it shouldn't).
Which is something I don't fully understand. Why wouldn't you want to have unified handling for all kinds of DSA tags, but would rather single out the Ethertype ones?

@guyharris
Copy link
Member

Currently:
we have LINKTYPE_/DLT_ values for "brcm", "brcm-prepend", "dsa", and "edsa", which is as it should be, as they're either type 1 or type 2 without a usable Ethertype value;
we use LINKTYPE_ETHERNET/DLT_EN10MB for "rtl4a" and "rtl8_4", which is as it probably should be, as they have an assigned Ethertype and the data following the Ethertype has fields that allow distinguishing between different formats (tags and on-the-Ethernet Realtek protocols);

As per your own criteria, you have edsa in the wrong category (it has its own link type but by your logic it shouldn't).

Sorry, I must not have stated my logic clearly enough.

As I understand it, the tag used by "edsa" begins with a 2-octet value that comes from a driver-settable register in the hardware, so there's no guarantee that somebody won't set it to 0x0800 or whatever and, even if it's set to the one value that the IEEE site says is assigned to Marvell, 0x22E3, we don't know for certain whether that might also be used for on-the-Ethernet protocols that cannot be reliably distinguished from EDSA tags.

Therefore, it belongs in the "type 2 without a usable Ethertype value" - or, perhaps, "known-to-be-usable Ethertype value".

Why wouldn't you want to have unified handling for all kinds of DSA tags, but would rather single out the Ethertype ones?

Because:

  • nothing in packets with type 1 tags can be properly dissected by an Ethernet dissector, so LINKTYPE_ETHERNET/DLT_EN10MB shouldn't be used for them;
  • the only parts of packets with type 2 tags that do not begin with an assigned Ethertype value will be the destination and source MAC addresses;
  • packets with type 2 tags that begin with an assigned Ethertype value, but where that value can also be used for other types of packets, would not be correctly dissectible without other out-of-band information, and a separate LINKTYPE_/DLT_ value is a good type of out-of-band information, as it doesn't require the user to manually provide it;
  • packets with type 3 tags can largely be dissected correctly, except perhaps if the tag is mistaken for the end of the Ethernet payload, and fixing that also requires out-of-band information.

@vladimiroltean
Copy link
Author

Ok, but confusingly you refer to type 2 tags with no usable EtherType as if there was any tag at all whose EtherType is in the IANA 802 numbers table. I don't think that's the case - none of them are.

@guyharris
Copy link
Member

Ok, but confusingly you refer to type 2 tags with no usable EtherType as if there was any tag at all whose EtherType is in the IANA 802 numbers table. I don't think that's the case - none of them are.

I know it's the case, as the Realtek tags are. They use Ethertype 0x8899, which is registered to "Realtek Semiconductor Corp.". Go to https://regauth.standards.ieee.org/standards-ra-web/pub/view.html#registries, select "EtherType(TM)" as the "Product", click the search button, enter 8899 in the filter box, and click "Filter".

@vladimiroltean
Copy link
Author

Here's what I've been able to extract from the kernel sources.

proto type length (bytes) xmit format rcv format
ar9331 1 2 15:14 - VERSION
13:12 - PRIORITY
10:8 - TYPE
7 - BROADCAST
6 - FROM_CPU
5:4 - RESERVED
3:0 - PORT_NUM
like xmit
brcm 2 w/o EtherType 4 already documented already documented
brcm-legacy 2 6 EtherType 0x8874
30:29 - TYPE
3:0 - PORT_ID
like rcv
brcm-prepend 1 4 like brcm like brcm
dsa 2 w/o EtherType 4 already documented already documented
edsa 2 8 already documented already documented
gswip 1 4 TX, 8 RX 26:24 - SLPID
18:16 - DPID
15 - PORT_MAP_EN
14 - PORT_MAP_SEL
13 - LRN_DIS
12 - CLASS_EN
11:8 - CLASS
6:1 - PORT_MAP
0 - DPID_EN
6:4 - SPPID
hellcreek 3 1 1:0 - PORT like xmit
ksz8795 3 1 7 - LOOKUP
6 - OVERRIDE
1:0 - PORT
1:0 - PORT
ksz9477 3 2 RX
6 RX with tstamp
1 TX
5 TX with tstamp
ksz9893 3 2 RX
6 RX with tstamp
1 TX
5 TX with tstamp
lan937x 3 2 TX
6 TX with tstamp
2 RX
6 RX with tstamp
lan9303 2 4 EtherType 0x8100
mtk 2 w/o EtherType 4
none no tag 0
ocelot 1 20
seville 1 20
ocelot-8021q 2 4 EtherType 0x8100
qca 2 w/o EtherType 2
rtl4a 2 4 EtherType 0x8899
rtl8_4 2 8 EtherType 0x8899
rtl8_4t 3 8 tail tag variant of rtl8_4
a5psw 2 8 EtherType 0xe001
sja1105 2 4 EtherType 0xdadb or 0x8100
sja1110 hybrid 4 TX
12 TX link local
(8 header, 4 trailer)
4 RX
21-36 RX link local
(8 header, 13 trailer, 0-15 padding)
EtherType 0xdadc
trailer 3 4
vsc73xx-8021q 2 4 EtherType 0x8100
xrs700x 3 1

@guyharris
Copy link
Member

Is "sja1105" just a standard VLAN tag if it has an Ethertype of 0x8100? 0xdadb doesn't appear to be in the IEEE database.

Are "lan9303", "ocelot-8021q", and "vsc73xx-8021q" all standard VLAN tags? (The "8021q" in the names of the latter two suggest that those two are.)

@vladimiroltean
Copy link
Author

They are all VLAN tags with specific meanings superimposed on top of the VID field. In the case of "sja1105", the TPID can either be 0x8100 or 0xdadb, depending on whether the switch is VLAN-aware or not - the TPID doesn't affect the interpretation of the other fields in the tag. The value of 0xdadb is self-assigned, no guarantee there won't appear a protocol using this EtherType in the future.
The field meanings are the same for "sja1105", "ocelot-8021q" and "vsc73xx-8021q" and documented here. For "lan9303", the meanings are different and documented here.

@guyharris
Copy link
Member

guyharris commented Feb 14, 2025

Of the non-8100 Ethertypes:

  • 8874 is assigned to Broadcom, so the only question is whether it's also used for any on-the-Ethernet protocols - Wireshark already dissects it as a "Broadcom MAC Management" tag;
  • 8899 is assigned to Realtek, and it's used for both tags and on-the-Ethernet protocols, but there's a subprotocol field that's used to distinguish between the various protocols for which it's used and the various tag types for which it's used (as dissected by Wireshark);
  • e001, dadb, and dadc are not in the IEEE database.

@guyharris
Copy link
Member

The value of 0xdadb is self-assigned, no guarantee there won't appear a protocol using this EtherType in the future.

So it's probably best to assign a LINKTYPE_/DLT_ for "sja1105" (that would also allow the VID field to be interpreted specially).

@vladimiroltean
Copy link
Author

vladimiroltean commented Feb 15, 2025

What does this all mean for this patch? Do you mean separate link types should be assigned now, when I really have no interest in writing a disector, or when?

@guyharris
Copy link
Member

What does this all mean for this patch?

My inclination right now is to expand the table of known tag types to include all he ones currently used in the Linux kernel, temporarily mapping all those that don't have LINKTYPE_/DLT_ values assigned to LINKTYPE_ETHERNET/DLT_EN10MB, add comments to all of them to indicate whether they're type 1, type 3, type 2 with a usable Ethertype, type 2 with at least one Ethertype being unreliable (self-assigned rather than IEEE-assigned), or type 2 without an Ethertype, and continue to return an error for unknown tag types.

If somebody adds a tag type, they should tell us about it, so we can add it to the list.

After that, we assign LINKTYPE_/DLT_ values to those that need them, update the table, and at least make tcpdump dissect them (and maybe add Wireshark after that).

guyharris added a commit to guyharris/libpcap that referenced this pull request Feb 15, 2025
Many of those entries need their own LINKTYPE_/DLT_? values, including
tcpdump and Wireshark support for same, but at least this lets you see
raw hex data from a capture.

Fixes the-tcpdump-group#1367.

Supercedes the-tcpdump-group#1451.
guyharris added a commit that referenced this pull request Feb 15, 2025
Many of those entries need their own LINKTYPE_/DLT_? values, including
tcpdump and Wireshark support for same, but at least this lets you see
raw hex data from a capture.

Fixes #1367.

Supercedes #1451.
guyharris added a commit that referenced this pull request Feb 15, 2025
Many of those entries need their own LINKTYPE_/DLT_? values, including
tcpdump and Wireshark support for same, but at least this lets you see
raw hex data from a capture.

Fixes #1367.

Supercedes #1451.

(backported from commit a8a6cd9)
@infrastation
Copy link
Member

Using DLT_EN10MB for unsupported DSA encodings introduces easy ways for things to go wrong, e.g. allows to run higher-level filters on wire encodings that do not match Ethernet in the first place. Guy earlier suggested using LINKTYPE_DSA_UNSUPPORTED, this seems a step in the correct direction to me.

If the DSA protocol/type is known at the capture time and there is no specific DLT for it, it would seem reasonable to state: "this is a DSA frame, it was captured on Linux and Linux indicated the variety of DSA was X". In other words, it could be something such as DLT_LINUX_DSA with at least one field that specifies the DSA type (possibly with a frame direction indicator). For those who cannot wait to see the data this DLT would be trivially printed as a hex dump. For those who want to develop code for filtering and dissecting it properly this DLT would provide the required information to do it (DLT_EN10MB does not even imply that the frame is DSA, let alone specific DSA type).

Does it make sense?

@infrastation
Copy link
Member

Alternatively, there could be something like DLT_RAW_BYTES with no claims about the origin or the structure of the packets, and naturally fit for hex dumps only.

@infrastation
Copy link
Member

@guyharris, do you mind if I prototype the changes to avoid mixing DSA into DLT_EN10MB?

@guyharris
Copy link
Member

@guyharris, do you mind if I prototype the changes to avoid mixing DSA into DLT_EN10MB?

Nope, go ahead.

@thomas725
Copy link

I have 3 routers which I upgraded to OpenWrt 24.10.0 (r28427-6df0e3d02a) today.
On two of them tcpdump now fails to start with this error:

tcpdump: unsupported DSA tag: mtk

  • Xiaomi Mi Router AX3000T
  • Xiaomi Mi Router 4A Gigabit Edition

Is there a reasonable simple way to install your fix on my devices without being either an OpenWRT nor libpcap developer, or do I need to downgrade OpenWRT to a previous version (how old does it need to be?) that doesn't have this bug?

@infrastation
Copy link
Member

According to OpenWrt device pages (AX3000T, 4A Gb), these devices are supported. Perhaps the documentation is not 100% accurate in every regard, but this is not uncommon. A paying customer of the vendor that makes these Xiaomi devices could make a point that OpenWrt developers didn't do a thorough QA for this combination of hardware and firmware, and the counter-points could be that OpenWrt is free software, the work is done by volunteers, no warranty implied etc. But this would not improve libpcap support for DSA on Linux, would it?

The workaround for these newer DSA types in libpcap is not yet complete. It is important to make sure it does not break other things for other users on Linux and other operating systems. It will take some time for the solution to reach the end users. Your best course of action would be rolling back to the previous working firmware and waiting until support for this hardware improves. Alternatively, you could try a different hardware that works out of the box. This has been my own experience with OpenWrt in the last ~13 years, and with open source software in general in the last ~25 years (that said, quite often users get the same experience after buying proprietary software). Sometimes such incomplete or lacking hardware support even motivates the users to become contributors or developers themselves.

In future, if anyone expects support for a particular new software or hardware in libpcap, please do your research/testing/QA as soon as you can and report any problems as soon as you can because the correct solution may be more complicated than it seems.

@mcr
Copy link
Member

mcr commented Feb 23, 2025

I think that you'll only see the DSA tags when dumping on the physical interface that connects to the switch.
So, on my ancient 3800, that means eth0. [eth1 is WAN link]. If you dump on the vlan or bridge interfaces, then you should not any DSA tags.

@olerem
Copy link

olerem commented Apr 15, 2025

Hi all. Are there any progress on this issue?

@infrastation
Copy link
Member

Thank you for waiting. As discussed, I have prototyped some code to introduce a new "opaque unstructured data" DLT and to use it in map_arphrd_to_dlt() and iface_dsa_get_proto_info(), then it became obvious the new DLT would mostly duplicate DLT_DOCSIS, which was introduced to solve a similar problem (which arguably no longer exists because the hardware has been EOL for quite a while). However, one meaningful difference is that in the Linux DSA case some implementations use a different encoding for different frame directions, so the new DLT would need to have a direction field. Then I paid attention to the comments in dsa_protos[] that suggested using DLT_LINUX_SLL for certain DSA types and noted that:

  • DLT_LINUX_SLL2 would be better because it would also save the interface index in a file.
  • DLT_LINUX_SLL2 could work better as the default DLT for all unsupported Linux DSA types.
  • In case it does not work exactly as expected, it would be nice to be able to test the changes before making a release.

Then I got distracted by other work. Would you be able to compile the proposed better solution when it becomes ready and to try it on the hardware with the unsupported DSA type?

@olerem
Copy link

olerem commented Apr 16, 2025

Sure, just ping me.

@guyharris
Copy link
Member

Then I paid attention to the comments in dsa_protos[] that suggested using DLT_LINUX_SLL for certain DSA types

I'm not sure whether that was my idea, or somebody else's suggestion that I added in comments, but I'm not sure it's the bet idea; DLT_LINUX_SLL and DLT_LINUX_SLL2 involve capturing from a PF_PACKET/SOCK_DGRAM socket, and, for those sockets, the Linux kernel strips off link-layer headers, presumably including the DSA header, so it wouldn't provide the DSA header even if it were only dissected as a raw binary blob.

What perhaps should be done is:

  1. first, have a LINKTYPE_LINUX_DSA_UNKNOWN/DLT_LINUX_DSA_UNKNOWN to which DSA types that don't yet have their own LINKTYPE_/DLT_ value are assigned - it would prepend a direction flag to the raw packet data (which I think can be done in the reserved space that memory-mapped capture provides, just as we prepend the SLL/SLL2 header for cooked captures), and have tcpdump just "dissect" that as raw hex data;
  2. then, over time, assign link-layer types to the DSA types that need them but don't have them and, if they have different transmit and receive headers, prepend a direction flag, and have tcpdump dissect them.

(And update Wireshark to support the new link-layer types as well.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

7 participants