NDNLPv2 is a link protocol for Named Data Networking.
NDNLPv2 provides the following features:
- fragmentation and reassembly: fragment a network layer packet to fit in link MTU
- reliability: reduce packet loss
- failure detection: rapidly detect link failure and recovery
- integrity: prevent packet injection
- forwarding instruction: NACK, nexthop choice, cache control, etc
- packet information: for management and monitoring
NDNLPv2 is designed to be a unified protocol that can be used on all kinds of links, including but not limited to: UNIX sockets, Ethernet unicast/multicast, UDP unicast/multicast, TCP connections, WebSockets, etc.
NDNLPv2 protocol operates as a link adaptation layer; it is above link layer and below network layer. Please, do not call this "layer 2.5": there is no such notion in RFC protocols.
Different links need different features, or different designs of a feature. NDNLPv2 ensures all features are optional and can be turned on or off per-link. NDNLPv2 also allows different designs of a feature to be adopted per-link.
NDNLPv2 deprecates and replaces: original NDNLP (aka NDNLPv1), NDNLPv1 multicast extension, NDNLPv1-TLV, NDNLP-BFD, NFD LocalControlHeader.
NDNLPv2 packet adopts a Type-Length-Value (TLV) structure similar to NDN Packet Format.
LpPacket ::= LP-PACKET-TYPE TLV-LENGTH
LpHeaderField*
Fragment?
Outermost packet transmitted on a NDNLPv2 link is LpPacket. In addition, a host MUST also accept bare network packets (Interest and Data) on a NDNLPv2 link, which SHOULD be interpreted as an LpPacket with the bare network packet as its LpFragment. However, such packets could be dropped later in processing if the link configured to require a certain NDNLPv2 feature but a field is missing.
LpHeaderField is a repeatable optional structure in LpHeader. NDNLPv2 features MAY add new header fields by extending the definition of LpHeaderField. Unless otherwise specified, the same field shall appear at most once. Unless otherwise specified, fields MUST appear in the order of increasing TLV-TYPE codes.
If an incoming LpPacket contains an unknown LpHeaderField, the following rules apply:
- if the unknown field is in range [800:959], and the least significant bit is 1, the receive SHOULD ignore the field, and continue processing the packet;
- otherwise, the receiver MUST drop the packet, but SHOULD NOT consider the link has an error.
Note: if a field is recognized but the relevant feature is disabled, it's not an "unknown field".
Initially, the Sequence header field is defined:
LpHeaderField ::= .. | Sequence
Sequence ::= SEQUENCE-TYPE TLV-LENGTH
fixed-width unsigned integer
Sequence contains a sequence number that is useful in multiple features. This field is REQUIRED if any enabled feature is using sequence numbers, otherwise it's OPTIONAL. Bit width of the sequence is determined on a per-link basis; 8-octet is recommended for today's links. A host MUST generate consecutive sequence numbers for outgoing packets on the same face.
Fragment ::= FRAGMENT-TYPE TLV-LENGTH
byte+
Fragment contains a fragment of one or more network layer packets. The fragmentation and reassembly feature defines how Fragment field is constructed and interpreted. When fragmentation and reassembly feature is disabled, the Fragment field contains a whole network layer packet. Fragment is OPTIONAL; LpPacket without Fragment is an IDLE packet.
Indexed fragmentation provides fragmentation and reassembly feature on datagram links that does not guarantee in-order delivery.
This feature defines two header fields:
LpHeaderField ::= .. | FragIndex | FragCount
FragIndex ::= FRAG-INDEX-TYPE TLV-LENGTH
nonNegativeInteger
FragCount ::= FRAG-COUNT-TYPE TLV-LENGTH
nonNegativeInteger
Sender slices a network layer packet into one or more fragments. The size of each fragment MUST be small enough so that the LpPacket carrying every fragment is below link MTU. It is RECOMMENDED that all except the last fragments have the same size.
FragCount field indicates the number of fragments belonging to the same network layer packet. It MUST be the same in all fragments belonging to the same network layer packet.
FragIndex field indicates the zero-based index of the current packet. It MUST be assigned consecutively for fragments belonging to the same network layer packet, starting from zero. The feature is named "indexed fragmentation" because every fragment is given an index in this field.
Sequence field is REQUIRED when this feature is enabled. Fragments belonging to the same network layer packet MUST be assigned consecutive sequence numbers, in the same order with FragIndex.
For example, a 5000-octet network layer packet may be sliced as illustrated:
+-------------+-------------+ +-------------+-------------+
| LpPacket | Fragment | | LpPacket | Fragment |
| seq=8801 | | | seq=8802 | |
| FragIndex=0 | [0:1400] | | FragIndex=1 | [1400:2800] |
| FragCount=4 | | | FragCount=4 | |
+-------------+-------------+ +-------------+-------------+
+-------------+-------------+ +-------------+-------------+
| LpPacket | Fragment | | LpPacket | Fragment |
| seq=8803 | | | seq=8804 | |
| FragIndex=2 | [2800:4200] | | FragIndex=3 | [4200:5000] |
| FragCount=4 | | | FragCount=4 | |
+-------------+-------------+ +-------------+-------------+
Receiver stores fragments in a PartialMessageStore data structure, which is a collection of PartialMessages, indexed by MessageIdentifier=Sequence-FragIndex. Since both Sequence and FragIndex are assigned consecutively, MessageIdentifier would be the sequence number of the first fragment of a network layer packet. After collecting all fragments belonging to a network layer packet, the receiver joins them together, and delivers the complete network layer packet to upper layer.
The receiver SHOULD maintain a reassembly timer in each PartialMessage, which is reset each time a new fragment is received. If this timer expires, the PartialMessage is dropped. Default duration for this timer is 500ms.
If this feature is enabled but FragIndex is missing, it is implied as zero. If this feature is enabled but FragCount is missing, it is implied as one. If this feature is disabled but either header field is received, the packet MUST be dropped.
Unless otherwise specified, header fields from other features shall only appear on the first fragment. If a field appear on a non-first fragment, it MUST be ignored.
A network NACK is a forwarding instruction from upstream to downstream that indicates the upstream is unable to satisfy an Interest.
This feature defines a header field:
LpHeaderField ::= .. | Nack
Nack ::= NACK-TYPE TLV-LENGTH
NackReason?
NackReason ::= NACK-REASON-TYPE TLV-LENGTH
nonNegativeInteger
Nack header field indicates an Interest is a NACK, and is not a normal Interest. The receiver MUST NOT process the packet as an Interest.
NackReason element MAY be included to indicate why the NACK is transmitted.
The following NackReason values are defined:
Code | Reason | Description |
---|---|---|
0 | Unknown | unspecified NACK reason |
1 | Duplicate | the upstream has detected a duplicate Nonce in the Interest sent by the downstream |
2 | GiveUp | the upstream has attempted to forward the Interest, but no Data can be retrieved after exhausting all available routes |
A receiver MUST be prepared to process a NACK without a reason.
If NackReason element contains an unrecognized reason, the receiver MUST treat this NACK as a NACK without reason, and MUST NOT drop the packet.
Example of NACK of an Interest for /example
with NACK reason "Duplicate":
+--------------------------+---------------+
| LpPacket | Interest |
| | Name=/example |
| +-Nack-----------------+ | Nonce=35 |
| | NackReason=Duplicate | | |
| +----------------------+ | |
+--------------------------+---------------+
It's RECOMMENDED to enable this feature on every link.
If this feature is disabled but Nack is received, the packet MUST be dropped.
Nack header field is permitted only on an LpPacket carrying an Interest.
When Nack appears on an LpPacket carrying a network layer packet other than an Interest, the packet MUST be dropped.
Consumer controlled forwarding allows a local consumer application to explicitly specify the nexthop face to forward an Interest.
This feature defines a header field:
LpHeaderField ::= .. | NextHopFaceId
NextHopFaceId ::= NEXT-HOP-FACE-ID-TYPE TLV-LENGTH
nonNegativeInteger
NextHopFaceId indicates the nexthop FaceId to which an Interest should be forwarded. A local consumer application MAY add this field to an LpPacket carrying an Interest. The local forwarder SHOULD follow this instruction and forward the Interest to the specified nexthop. ContentStore lookup SHOULD be bypassed unless NextHopFaceId equals a special FaceId that represent the ContentStore.
This feature is designed to be used on local faces only. It SHOULD NOT be enabled on non-local faces. If this feature is enabled but NextHopFaceId refers to a non-existent face, the Interest SHOULD be processed as if there is no available route. If this feature is disabled but NextHopFaceId is received, the packet SHOULD be dropped, or this field MUST be ignored.
NextHopFaceId header field is permitted only on an LpPacket carrying an Interest, from an application to the forwarder. When NextHopFaceId appears on an LpPacket carrying a network layer packet other than an Interest, the packet MUST be dropped. When NextHopFaceId is received by an application from a forwarder, this field MUST be ignored.
Implementation note: Currently, NFD honors NextHopFaceId only if client-control strategy is chosen for the namespace. In addition, ContentStore lookup will not be bypassed. This limitation may be lifted in a future version of NFD.
Local cache policy feature allows a local producer application to instruct ContentStore on whether and how to cache a Data packet.
This feature defines a header field:
LpHeaderField ::= .. | CachingPolicy
CachingPolicy ::= CACHING-POLICY-TYPE TLV-LENGTH
NoCache
NoCache ::= NO-CACHE-TYPE TLV-LENGTH(=0)
CachingPolicy contains a sub-element that gives a suggestion to the ContentStore. The ContentStore MAY follow this suggestion.
A policy element, such as NoCache, MUST appear under CachingPolicy to give a suggestion to the ContentStore. Although all defined policy elements are empty, a policy element to be defined in the future may be non-empty and carry additional arguments. If CachingPolicy field contains an unknown policy element, the forwarder SHOULD drop the packet.
+-------------------+---------------+
| LpPacket | Data |
| | Name=/example |
| +-CachingPolicy-+ | Content=xxxx |
| | NoCache | | Signature=xx |
| +---------------+ | |
+-------------------+---------------+
NoCache indicates the ContentStore SHOULD NOT admit the Data packet.
This feature is designed to be used on local faces only. It SHOULD NOT be enabled on non-local faces. If this feature is disabled but CachingPolicy is received, this field MUST be ignored.
CachingPolicy header field is permitted only on an LpPacket carrying a Data packet, from an application to the forwarder. When CachingPolicy header field appears on an LpPacket carrying a network layer packet other than a Data packet, the packet MUST be dropped. When CachingPolicy is received by an application from a forwarder, this field MUST be ignored.
Incoming face indication feature allows the forwarder to inform local applications about the face on which a packet is received.
This feature defines a header field:
LpHeaderField ::= .. | IncomingFaceId
IncomingFaceId ::= INCOMING-FACE-ID-TYPE TLV-LENGTH
nonNegativeInteger
IncomingFaceId contains the FaceId from which the network layer packet is received. When this feature is enabled, the forwarder SHOULD attach this field to every network layer packet going to a local application, and indicate the FaceId on which this network layer packet is received by the forwarder. If a Data packet comes from the ContentStore, IncomingFaceId SHOULD contain a special FaceId that represents the ContentStore, rather than the FaceId on which this Data packet was originally received. Even if this feature is enabled, the application MUST be prepared to receive a packet without IncomingFaceId field.
This feature is designed to be used on local faces only. It SHOULD NOT be enabled on non-local faces.
IncomingFaceId header field is permitted only on an LpPacket from the forwarder to an application. When IncomingFaceId is received by the forwarder from an application, this field MUST be ignored.
type | code (decimal) | code (hexadecimal) |
---|---|---|
LpPacket | 100 | 0x64 |
Fragment | 80 | 0x50 |
Sequence | 81 | 0x51 |
FragIndex | 82 | 0x52 |
FragCount | 83 | 0x53 |
Nack | 800 | 0x0320 |
NackReason | 801 | 0x0321 |
NextHopFaceId | 816 | 0x0330 |
CachingPolicy | 820 | 0x0334 |
NoCache | 821 | 0x0335 |
IncomingFaceId | 817 | 0x0331 |
Two blocks of TLV-TYPE codes have been reserved by link protocols:
- [80:100], 1-octet encoding
- [800:1000], 3-octet encoding
TLV-TYPE codes for LpHeaderField SHOULD be assigned according to the following rules:
- if the field can be safely ignored by a receiver that doesn't understand the field, pick an unused code in [800:959] range whose least significant 2-bits are 00.
- if the field would occur frequently, pick an unused code in [81:99] range.
- otherwise, pick an unused code in [800:959] range whose least sigificant 2-bits are 01.
Note: code assignment for a TLV-TYPE nested within a LpHeaderField is not restricted by the above rules.