I have a simple protocol consisting of lets say 4 fields:
Field-1 (4-bits)
Field-2 (6-bits)
Field-3 (4-bits)
Field-4 (2-bits)
Currently, I organize them so they are byte-aligned as:
Field-1,Field-3,Field-2,Field-4
In total, the message occupies 2 bytes with 0 bytes overhead.
To make this backwards compatible, so I can understand messages from a previous version I add a 1-byte version field at the beginning and it becomes:
Version-Field,Field-1,Field-3,Field-2,Field-4
3 bytes in total with an overhead of 1 byte.
How do I add forwards compatibility such that I can add new fields in new versions of the protocol while ensuring old versions of the software can still understand the messages, with the lowest possible overhead?
You'll have FC by ensuring strict BC with this rule:
If you can follow the rule, you'll automatically have both BC and FC. Consequently, with the rule you can only add new fields by appending them to existing layout.
Let me explain with an example. Say that you need to add these fields for version 2:
Remember the rule, new fields can only be appended to existing layout. So, this is version 2 message layout:
Because the layout known to version 1 is intact, your version 1 code can read messages of any version with this (pseudocode):
Version 1 doesn't need to check the version field because the known layout is unconditional. However, version 2 and all other versions will need to check the version field. Assuming that we use the value 2 to indicate version 2, this will do (pseudocode):
The most important part of the code is the fact that it reuses code from the previous version and this check:
Version 3 of the code can simply follow version 2 like this:
Think of it as a template for future versions. By following the rule and the examples, any version of the protocol can read messages from any version with just 1 byte overhead.