IPN Naming Scheme Transition Guide
Table of Contents
- Introduction
- Overview of 3-Part IPN Naming
- Structure Field Name Changes
- Function Parameter Changes
- Code Migration Examples
- FQNN Representation in Logs and Internal State
Introduction
Starting with ION version 4.1.4-a.1, ION introduced support for a 3-part IPN naming scheme using Fully Qualified Node Numbers (FQNN) instead of simple node numbers. This change enables hierarchical node addressing with an optional allocator component, which is essential for large-scale DTN deployments where node number management needs to be delegated across multiple administrative domains.
This document describes the changes developers need to make when updating code that references the older Node-based structures to the new FQNN-based structures.
Overview of 3-Part IPN Naming
Old 2-Part IPN Format
New 3-Part IPN Format
ipn:[allocator.]<node>.<service>
Examples:
ipn:5.23 (node 5, service 23 - backwards compatible)
ipn:1.5.23 (allocator 1, node 5, service 23)
FQNN Encoding
The FQNN is a 64-bit unsigned integer (uvast) that encodes both the allocator and node number:
For backwards compatibility, when no allocator is specified, the allocator portion is zero, and the FQNN equals the node number.
Structure Field Name Changes
The following table summarizes all field name changes across ION structures:
IonCXref (Contact Cross-Reference)
| Old Field | New Field | Type | Description |
|---|---|---|---|
fromNode |
fromFqnn |
uvast |
Source node FQNN |
toNode |
toFqnn |
uvast |
Destination node FQNN |
IonRXref (Range Cross-Reference)
| Old Field | New Field | Type | Description |
|---|---|---|---|
fromNode |
fromFqnn |
uvast |
Source node FQNN |
toNode |
toFqnn |
uvast |
Destination node FQNN |
IonContact
| Old Field | New Field | Type | Description |
|---|---|---|---|
fromNode |
fromFqnn |
uvast |
Source node FQNN |
toNode |
toFqnn |
uvast |
Destination node FQNN |
IonRange
| Old Field | New Field | Type | Description |
|---|---|---|---|
fromNode |
fromFqnn |
uvast |
Source node FQNN |
toNode |
toFqnn |
uvast |
Destination node FQNN |
IonNode
| Old Field | New Field | Type | Description |
|---|---|---|---|
nodeNbr |
fqnn |
uvast |
Node's fully qualified node number |
IonNeighbor
| Old Field | New Field | Type | Description |
|---|---|---|---|
nodeNbr |
fqnn |
uvast |
Neighbor's fully qualified node number |
IonProbe
| Old Field | New Field | Type | Description |
|---|---|---|---|
destNodeNbr |
destFqnn |
uvast |
Destination FQNN |
neighborNodeNbr |
neighborFqnn |
uvast |
Neighbor FQNN |
RegionMember
| Old Field | New Field | Type | Description |
|---|---|---|---|
nodeNbr |
fqnn |
uvast |
Member's fully qualified node number |
IonDB
| Old Field | New Field | Type | Description |
|---|---|---|---|
ownNodeNbr |
ownFqnn |
uvast |
This node's fully qualified node number |
Function Parameter Changes
RFX API Functions (rfx.h)
| Old Signature | New Signature |
|---|---|
rfx_insert_contact(..., uvast fromNode, uvast toNode, ...) |
rfx_insert_contact(..., uvast fromFqnn, uvast toFqnn, ...) |
rfx_insert_range(..., uvast fromNode, uvast toNode, ...) |
rfx_insert_range(..., uvast fromFqnn, uvast toFqnn, ...) |
rfx_remove_contact(..., uvast fromNode, uvast toNode, ...) |
rfx_remove_contact(..., uvast fromFqnn, uvast toFqnn, ...) |
rfx_remove_range(..., uvast fromNode, uvast toNode, ...) |
rfx_remove_range(..., uvast fromFqnn, uvast toFqnn, ...) |
rfx_contact_state(uvast nodeNbr, ...) |
rfx_contact_state(uvast fqnn, ...) |
findNeighbor(IonVdb *vdb, uvast nodeNbr, ...) |
findNeighbor(IonVdb *vdb, uvast fqnn, ...) |
findNode(IonVdb *vdb, uvast nodeNbr, ...) |
findNode(IonVdb *vdb, uvast fqnn, ...) |
addEmbargo(IonNode *node, uvast neighborNodeNbr) |
addEmbargo(IonNode *node, uvast neighborFqnn) |
removeEmbargo(IonNode *node, uvast neighborNodeNbr) |
removeEmbargo(IonNode *node, uvast neighborFqnn) |
Utility Functions
| Old Function | New Function |
|---|---|
getOwnNodeNbr() |
getOwnFqnn() |
Code Migration Examples
Example 1: Accessing Contact Information
Old Code:
if (cxref->fromNode == getOwnNodeNbr())
{
neighbor = getNeighbor(vdb, cxref->toNode);
CHKERR(neighbor);
neighbor->xmitRate = 0;
}
New Code:
if (cxref->fromFqnn == getOwnFqnn())
{
neighbor = getNeighbor(vdb, cxref->toFqnn);
CHKERR(neighbor);
neighbor->xmitRate = 0;
}
Example 2: Initializing Contact Search Arguments
Old Code:
IonCXref arg;
memset((char *) &arg, 0, sizeof(IonCXref));
arg.fromNode = sourceNode;
arg.toNode = destNode;
New Code:
IonCXref arg;
memset((char *) &arg, 0, sizeof(IonCXref));
arg.fromFqnn = sourceFqnn;
arg.toFqnn = destFqnn;
Example 3: Inserting Contacts
Old Code:
rfx_insert_contact(_regionNbr(NULL), MAX_POSIX_TIME, MAX_POSIX_TIME,
getOwnNodeNbr(), getOwnNodeNbr(), 0, 1.0, &xaddr, _announce(NULL));
New Code:
rfx_insert_contact(_regionNbr(NULL), MAX_POSIX_TIME, MAX_POSIX_TIME,
getOwnFqnn(), getOwnFqnn(), 0, 1.0, &xaddr, _announce(NULL));
Example 4: Comparing Node Identifiers
Old Code:
if (contact->fromNode > argContact->fromNode) return 1;
if (contact->toNode < argContact->toNode) return -1;
New Code:
if (contact->fromFqnn > argContact->fromFqnn) return 1;
if (contact->toFqnn < argContact->toFqnn) return -1;
FQNN Representation in Logs and Internal State
When examining ION's internal state variables or log reports, you may encounter FQNN values displayed in different formats. It is important to understand that these different representations refer to the same underlying node.
64-Bit Integer Representation
Internal state variables and some log messages display the FQNN as a single 64-bit integer:
In this example:
- 4294967301 = allocator 1, node 5 (encoded as (1 << 32) + 5)
- 4294967302 = allocator 1, node 6 (encoded as (1 << 32) + 6)
3-Part Dotted Representation
User-facing commands and configuration files use the human-readable 3-part format:
This represents a contact from node 1.5 (allocator 1, node 5) to node 1.6 (allocator 1, node 6).
Converting Between Representations
To interpret a 64-bit FQNN value:
uvast fqnn = 4294967301; // Example FQNN value
uint32_t allocator = (uint32_t)(fqnn >> 32); // Upper 32 bits
uint32_t nodeNbr = (uint32_t)(fqnn & 0xFFFFFFFF); // Lower 32 bits
// Result: allocator = 1, nodeNbr = 5
// Displayed as: 1.5
To construct an FQNN from allocator and node number:
uint32_t allocator = 1;
uint32_t nodeNbr = 5;
uvast fqnn = ((uvast)allocator << 32) | nodeNbr;
// Result: fqnn = 4294967301
Backwards Compatibility
For nodes without an allocator (allocator = 0), the FQNN equals the node number:
| Node Number | Allocator | FQNN (64-bit) | Display Format |
|---|---|---|---|
| 5 | 0 | 5 | 5 or 0.5 |
| 5 | 1 | 4294967301 | 1.5 |
| 100 | 2 | 8589934692 | 2.100 |
Practical Tips
-
Log Analysis: When you see large integers (> 4 billion) in contact or range logs, they likely represent 3-part FQNNs with a non-zero allocator.
-
Debugging: Use the conversion formulas above to decode FQNN values when debugging.
-
Configuration: Always use the dotted notation in configuration files for clarity.
-
Comparison: Two representations are equivalent if they encode the same allocator and node number, regardless of display format.
Document Version: 1.0 Last Updated: 2025-12-02 Applies to: ION 4.1.4-a.1 and later