A protocol team adds a feature to the next generation of their link: a new header bit meaning "this packet may be reordered". Old devices were built years ago and will be in service for years more. The first time a new device sends the bit to an old one, the old receiver, which was written to check that the bit is 0, rejects the packet as malformed. The new feature has broken every installed device.
How does a protocol add features without breaking the devices already built to its older versions?
The obvious answer is to bump the version and require everyone to upgrade. Hardware cannot be upgraded: chips in the field keep the protocol they were built with. Any new generation has to work with every older one it might meet, and ideally old devices should keep working when they meet things newer than themselves. Compatibility has to be designed in from the first version, because it is the old devices' behaviour that decides whether new features are possible.
Technique | What it gives | Rule it needs |
|---|---|---|
Reserved fields | Room for future features | Senders set them to 0; receivers ignore them (do not check them) |
Ignore what you do not understand | Old receivers tolerate new optional content | Unknown optional fields, message types or capabilities are skipped, not rejected |
Negotiated features | New behaviour used only when both support it | Advertise in training or configuration (lesson 11.5); default to off |
Version fields | Each side knows what the other implements | Exchanged early; each side operates at the lower version |
Capability lists | Features added without fixed layouts | A linked list of capability blocks each with an ID; skip unknown IDs |
The key asymmetry: backward compatibility (new devices work with old ones) is achieved by the new side, which can know about the old. Forward compatibility (old devices tolerate new ones) depends on rules the old side followed from the start: ignore reserved bits, skip unknown capabilities. If the first version got those rules wrong, later versions are stuck.
Protocol | How it evolves |
|---|---|
PCI Express | Each generation trains at the highest rate both ends support and falls back to older ones; new features are advertised in capability structures found by walking a linked list, and software skips IDs it does not know. |
AXI | Later versions add optional signals with defined default values, so an interface without them connects to one that has them by tying the defaults. |
USB | A newer device or host works at the highest speed and version both support; descriptors report the version. |
DCLink | Training words carry speed and lanes (step 10); a version field and feature bits would extend the same exchange. |
The opening failure (illustrative) came from one line in the old receiver's checker: it rejected packets with any reserved bit set. The specification had said "reserved, set to 0", and the designer had checked it to be safe. The new feature had to be moved into a negotiated mode, used only after both sides advertised it, which cost a year. Specifications now say "reserved: senders set to 0, receivers ignore" explicitly.
Backward: the new side, which knows the old protocol. Forward: the old side, by having followed ignore-what-you-do-not-understand rules from the start.
An old partner cannot know about it; using it only after both advertise it guarantees nobody receives behaviour it does not understand.
Installed hardware cannot be upgraded; every generation must work with older ones.
Reserved fields, ignore-unknown rules, negotiated features, version fields and capability lists let protocols grow.
Forward compatibility is decided in version 1: senders set reserved to 0, receivers ignore it.