Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 1 | Type-Length-Value (TLV) Encoding |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 2 | ================================ |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 3 | |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 4 | Each NDN packet is encoded in :abbr:`TLV (Type-Length-Value)` format. |
| 5 | NDN Interest and Data packets are distinguished by the type number in the first and outermost TLV\ :sub:`0`\ . |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 6 | |
| 7 | An NDN packet is mainly a collection of TLVs inside TLV\ :sub:`0`\ . Some TLVs may contain sub-TLVs, and each sub-TLV may also be further nested. A guiding design principle is to keep the order of TLV\ :sub:`i`\ s deterministic, and keep the level of nesting as small as possible to minimize both processing overhead and chances for errors. |
| 8 | |
| 9 | Note that NDN packet format does not have a fixed packet header nor does it encode a protocol version number. Instead the design uses the TLV format to provide the flexibility of adding new types and phasing out old types as the protocol evolves over time. The absence of a fixed header makes it possible to support packets of very small sizes efficiently, without the header overhead. |
| 10 | There is also no packet fragmentation support at network level. |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 11 | Whenever needed, NDN packets may be fragmented and reassembled hop-by-hop\ [#f1]_. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 12 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 13 | |
Davide Pesavento | acaccaf | 2022-03-06 19:00:06 -0500 | [diff] [blame] | 14 | Variable-Size Encoding for Type and Length |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 15 | ------------------------------------------ |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 16 | |
Davide Pesavento | 23e340c | 2021-12-03 04:52:22 -0500 | [diff] [blame] | 17 | .. note:: |
| 18 | The text below and that in the :ref:`TLV` section are adapted from an earlier packet specification draft by Mark Stapp. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 19 | |
| 20 | To minimize the overhead during early deployment and to allow flexibility of future protocol extensions to meet unforeseeable needs, both type (T) and length (L) take a variable size format. |
| 21 | For implementation simplicity, both type and length take the same encoding format. |
| 22 | |
| 23 | We define a variable-length encoding for numbers in NDN as follows:: |
| 24 | |
Davide Pesavento | 23e340c | 2021-12-03 04:52:22 -0500 | [diff] [blame] | 25 | VAR-NUMBER-1 = %x00-FC |
| 26 | VAR-NUMBER-3 = %xFD 2OCTET |
| 27 | VAR-NUMBER-5 = %xFE 4OCTET |
| 28 | VAR-NUMBER-9 = %xFF 8OCTET |
| 29 | |
| 30 | .. note:: |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 31 | The formal grammar of the NDN packet format in this specification is given using :rfc:`Augmented BNF for Syntax Specifications <5234>`. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 32 | |
Junxiao Shi | 1082b42 | 2017-07-18 23:37:52 +0000 | [diff] [blame] | 33 | The first octet of the number either carries the actual number, or signals that a multi-octet encoding is present, as defined below: |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 34 | |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 35 | - If the first octet is less than or equal to 252 (``0xFC``), the number is encoded in that octet. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 36 | |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 37 | - If the first octet is 253 (``0xFD``), the number is encoded in the following 2 octets, in network byte-order. |
| 38 | This number must be greater than 252 (``0xFC``). |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 39 | |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 40 | - If the first octet is 254 (``0xFE``), the number is encoded in the following 4 octets, in network byte-order. |
| 41 | This number must be greater than 65535 (``0xFFFF``). |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 42 | |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 43 | - If the first octet is 255 (``0xFF``), the number is encoded in the following 8 octets, in network byte-order. |
| 44 | This number must be greater than 4294967295 (``0xFFFFFFFF``). |
Junxiao Shi | 459e466 | 2019-05-31 15:28:03 +0000 | [diff] [blame] | 45 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 46 | A number MUST be encoded using the shortest possible format. |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 47 | For example, the number 1024 is encoded as ``%xFD0400`` in ``VAR-NUMBER-3`` format, not ``%xFE00000400`` in ``VAR-NUMBER-5`` format. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 48 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 49 | |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 50 | .. _TLV: |
| 51 | |
Davide Pesavento | 751939c | 2020-06-26 22:16:24 -0400 | [diff] [blame] | 52 | NDN TLV Encoding |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 53 | ---------------- |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 54 | |
Alexander Afanasyev | 4b89611 | 2014-06-23 21:47:15 -0700 | [diff] [blame] | 55 | TLV encoding for NDN packets is defined as follows:: |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 56 | |
Junxiao Shi | 78ce295 | 2019-05-07 15:34:00 -0400 | [diff] [blame] | 57 | NDN-TLV = TLV-TYPE TLV-LENGTH TLV-VALUE |
Junxiao Shi | 459e466 | 2019-05-31 15:28:03 +0000 | [diff] [blame] | 58 | TLV-TYPE = VAR-NUMBER-1 / VAR-NUMBER-3 / VAR-NUMBER-5 |
| 59 | TLV-LENGTH = VAR-NUMBER-1 / VAR-NUMBER-3 / VAR-NUMBER-5 / VAR-NUMBER-9 |
Junxiao Shi | 78ce295 | 2019-05-07 15:34:00 -0400 | [diff] [blame] | 60 | TLV-VALUE = *OCTET |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 61 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 62 | ``TLV-TYPE`` MUST be in the range [1, 4294967295]. |
| 63 | Type 0 is reserved to indicate an invalid TLV element and MUST NOT appear on the wire. |
| 64 | ``TLV-TYPE`` SHOULD be unique at all nested levels. |
| 65 | Section :ref:`types` of this document lists the initial ``TLV-TYPE`` assignments. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 66 | |
Junxiao Shi | 1082b42 | 2017-07-18 23:37:52 +0000 | [diff] [blame] | 67 | The ``TLV-LENGTH`` field indicates number of bytes that ``TLV-VALUE`` uses. |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 68 | It does not include the number of bytes that ``TLV-TYPE`` and ``TLV-LENGTH`` fields themselves occupy. |
| 69 | In particular, a TLV element with empty value will have ``TLV-LENGTH`` equal to 0. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 70 | |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 71 | This encoding offers a reasonable balance between compactness and flexibility. |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 72 | Most common, standardized ``TLV-TYPE`` numbers will be allocated from a small-integer number-space, and these common types will be able to use the compact, single-byte encoding. |
| 73 | |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 74 | |
Davide Pesavento | 751939c | 2020-06-26 22:16:24 -0400 | [diff] [blame] | 75 | Non-Negative Integer Encoding |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 76 | ----------------------------- |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 77 | |
Davide Pesavento | f9353df | 2020-06-21 19:19:56 -0400 | [diff] [blame] | 78 | A number of TLV elements in the NDN packet format take a non-negative integer as their TLV-VALUE, with the following definition:: |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 79 | |
Davide Pesavento | f9353df | 2020-06-21 19:19:56 -0400 | [diff] [blame] | 80 | NonNegativeInteger = 1OCTET / 2OCTET / 4OCTET / 8OCTET |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 81 | |
Davide Pesavento | f9353df | 2020-06-21 19:19:56 -0400 | [diff] [blame] | 82 | The TLV-LENGTH of the TLV element enclosing a ``NonNegativeInteger`` MUST be either 1, 2, 4, or 8. |
| 83 | Depending on the TLV-LENGTH, a ``NonNegativeInteger`` is encoded as follows: |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 84 | |
Davide Pesavento | f9353df | 2020-06-21 19:19:56 -0400 | [diff] [blame] | 85 | - if the length is 1, the ``NonNegativeInteger`` is encoded in 1 octet; |
| 86 | - if the length is 2, the ``NonNegativeInteger`` is encoded in 2 octets, in network byte-order; |
| 87 | - if the length is 4, the ``NonNegativeInteger`` is encoded in 4 octets, in network byte-order; |
| 88 | - if the length is 8, the ``NonNegativeInteger`` is encoded in 8 octets, in network byte-order. |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 89 | |
Davide Pesavento | ec74676 | 2020-06-24 22:57:31 -0400 | [diff] [blame] | 90 | The following shows a few examples of TLVs that have a ``NonNegativeInteger`` as their value component in hexadecimal format (where ``TT`` represents the TLV-TYPE, followed by the TLV-LENGTH, and then the TLV-VALUE): |
| 91 | |
| 92 | .. code-block:: none |
Alexander Afanasyev | eee8c25 | 2013-11-21 23:22:41 +0000 | [diff] [blame] | 93 | |
| 94 | 0 => TT0100 |
| 95 | 1 => TT0101 |
| 96 | 255 => TT01FF |
| 97 | 256 => TT020100 |
| 98 | 65535 => TT02FFFF |
| 99 | 65536 => TT0400010000 |
Alexander Afanasyev | e9f4851 | 2018-01-15 23:44:50 -0500 | [diff] [blame] | 100 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 101 | |
Junxiao Shi | 707ea00 | 2018-07-17 15:42:52 -0400 | [diff] [blame] | 102 | .. _evolvability: |
| 103 | |
Alexander Afanasyev | e9f4851 | 2018-01-15 23:44:50 -0500 | [diff] [blame] | 104 | Considerations for Evolvability of TLV-Based Encoding |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 105 | ----------------------------------------------------- |
Alexander Afanasyev | e9f4851 | 2018-01-15 23:44:50 -0500 | [diff] [blame] | 106 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 107 | To ensure that the TLV-based protocol can evolve over time without requiring flag days, the least significant bit of ``TLV-TYPE`` (unless overridden by the specification of a particular network/library/application TLV element) is reserved to indicate whether that TLV element is *critical* or *non-critical*. |
Alexander Afanasyev | e9f4851 | 2018-01-15 23:44:50 -0500 | [diff] [blame] | 108 | A compliant TLV format decoder should follow the order, quantity, and presence requirements of the recognized elements defined in the corresponding specification. |
Davide Pesavento | 3c0bc31 | 2020-05-18 22:03:09 -0400 | [diff] [blame] | 109 | At the same time, if the decoder encounters an unrecognized or out-of-order element, the behavior should be as follows: |
Alexander Afanasyev | e9f4851 | 2018-01-15 23:44:50 -0500 | [diff] [blame] | 110 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 111 | - if the least significant bit of the element's ``TLV-TYPE`` number is 1, abort decoding and report an error; |
| 112 | - if the least significant bit of the element's ``TLV-TYPE`` number is 0, ignore the element and continue decoding; |
| 113 | - ``TLV-TYPE`` numbers in the range [0, 31] are "grandfathered" and are all designated as *critical* for the purposes of packet processing. |
Alexander Afanasyev | e9f4851 | 2018-01-15 23:44:50 -0500 | [diff] [blame] | 114 | |
| 115 | .. note:: |
Davide Pesavento | 23e340c | 2021-12-03 04:52:22 -0500 | [diff] [blame] | 116 | A recognized element is considered out-of-order if it appears in the element order that violates a specification. For example: |
| 117 | |
| 118 | - when a specification defines a sequence {``F1`` ``F2`` ``F3``}, an element ``F3`` would be out-of-order in the sequence {``F1`` ``F3`` ``F2``}; |
| 119 | - for {``F1`` ``F2?`` ``F3``} specification (i.e., when ``F2`` is optional, ``F2`` would be out-of-order in the same sequence {``F1`` ``F3`` ``F2``}. |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 120 | |
Davide Pesavento | ec288fe | 2022-11-26 18:28:01 -0500 | [diff] [blame] | 121 | |
Davide Pesavento | 4d6c357 | 2022-05-27 12:05:05 -0400 | [diff] [blame] | 122 | .. rubric:: Footnotes |
| 123 | |
| 124 | .. [#f1] `"Packet Fragmentation in NDN: Why NDN Uses Hop-By-Hop Fragmentation (NDN Memo)" by A. Afanasyev, J. Shi, L. Wang, B. Zhang, and L. Zhang., NDN Memo, Technical Report NDN-0032 <https://named-data.net/publications/techreports/ndn-0032-1-ndn-memo-fragmentation/>`__ |