RFC 926

Protocol for providing the connectionless mode network services

๐Ÿ“… published December 1984, from ietf

RFC 926 ๐ŸŽ€ Protocol for Providing the Connectionless-Mode Network Services

Okay bestie, this one is the RFC version of ISO DIS 8473 ๐Ÿ’– Its nickname is (Informally - ISO IP), and it's a whole protocol for connectionless-mode network services, so it's giving core internet plumbing ๐Ÿงš

Here's the title block tea โ˜•

  • It was put together by ISO, and sits in the Network Working Group ๐ŸŒธ
  • The name at the bottom of the note is Alex McKenzie from BBN ๐Ÿซถ
  • It's dated December 1984 ๐Ÿ“…
  • It's informational only, so it does not specify a standard for the ARPA-Internet, and the distribution is unlimited โœจ
  • The document doesn't say it obsoletes or updates anything, so there's nothing listed there ๐Ÿฆ‹

Status of this Memo

This document is distributed as an RFC for information only. It does not specify a standard for the ARPA-Internet. Distribution of this memo is unlimited.

Note

This document has been prepared by retyping the text of ISO DIS 8473 of May 1984, which is currently undergoing voting within ISO as a Draft International Standard (DIS). Although this RFC has been reviewed after typing, and is believed to be substantially correct, it is possible that typographic errors not present in the ISO document have been overlooked. ๐Ÿ™ˆ

Alex McKenzie, BBN

TABLE OF CONTENTS ๐Ÿ’…

 1   SCOPE AND FIELD OF APPLICATION........................ 2

 2   REFERENCES............................................ 3

 3   DEFINITIONS........................................... 4
 3.1   Reference Model Definitions......................... 4
 3.2   Service Conventions Definitions..................... 4
 3.3   Network Layer Architecture Definitions.............. 4
 3.4   Network Layer Addressing Definitions................ 5
 3.5   Additional Definitions.............................. 5

 4   SYMBOLS AND ABBREVIATIONS............................. 7
 4.1   Data Units.......................................... 7
 4.2   Protocol Data Units................................. 7
 4.3   Protocol Data Unit Fields........................... 7
 4.4   Parameters.......................................... 8
 4.5   Miscellaneous....................................... 8

 5   OVERVIEW OF THE PROTOCOL.............................. 9
 5.1   Internal Organization of the Network Layer.......... 9
 5.2   Subsets of the Protocol............................. 9
 5.3   Addressing......................................... 10
 5.4   Service Provided by the Network Layer.............. 10
 5.5   Service Assumed from the Subnetwork Service
    Provider.............................................. 11
 5.5.1   Subnetwork Addresses............................. 12
 5.5.2   Subnetwork Quality of Service.................... 12
 5.5.3   Subnetwork User Data............................. 13
 5.5.4   Subnetwork Dependent Convergence Functions....... 13
 5.6   Service Assumed from Local Evironment.............. 14

 6   PROTOCOL FUNCTIONS................................... 16
 6.1   PDU Composition Function........................... 16
 6.2   PDU Decomposition Function......................... 17
 6.3   Header Format Analysis Function.................... 17
 6.4   PDU Lifetime Control Function...................... 18
 6.5   Route PDU Function................................. 18
 6.6   Forward PDU Function............................... 19
 6.7   Segmentation Function.............................. 19
 6.8   Reassembly Function................................ 20
 6.9   Discard PDU Function............................... 21
 6.10   Error Reporting Function.......................... 22
 6.10.1   Overview........................................ 22
 6.10.2   Requirements.................................... 23
 6.10.3   Processing of Error Reports..................... 24
 6.11   PDU Header Error Detection........................ 25
 6.12   Padding Function.................................. 26
 6.13   Security.......................................... 26
 6.14   Source Routing Function........................... 27
 6.15   Record Route Function............................. 28
 6.16   Quality of Service Maintenance Function........... 29
 6.17   Classification of Functions....................... 29

 7   STRUCTURE AND ENCODING OF PDUS....................... 32
 7.1   Structure.......................................... 32
 7.2   Fixed Part......................................... 34
 7.2.1   General.......................................... 34
 7.2.2   Network Layer Protocol Identifier................ 34
 7.2.3   Length Indicator................................. 35
 7.2.4   Version/Protocol Identifier Extension............ 35
 7.2.5   PDU Lifetime..................................... 35
 7.2.6   Flags............................................ 36
 7.2.6.1   Segmentation Permitted and More Segments Flags. 36
 7.2.6.2   Error Report Flag.............................. 37
 7.2.7   Type Code........................................ 37
 7.2.8   PDU Segment Length............................... 37
 7.2.9   PDUChecksum...................................... 38
 7.3   Address Part....................................... 38
 7.3.1   General.......................................... 38
 7.3.1.1     Destination and Source Address Information... 39

 7.4   Segmentation Part.................................. 40
 7.4.1   Data Unit Identifier............................. 41
 7.4.2   Segment Offset................................... 41
 7.4.3   PDU Total Length................................. 41
 7.5   Options Part....................................... 41
 7.5.1   General.......................................... 41
 7.5.2   Padding.......................................... 43
 7.5.3   Security......................................... 43
 7.5.4   Source Routing................................... 44
 7.5.5   Recording of Route............................... 45
 7.5.6   Quality of Service Maintenance................... 46
 7.6   Priority........................................... 47
 7.7   Data Part.......................................... 47
 7.8   Data (DT) PDU...................................... 49
 7.8.1   Structure........................................ 49
 7.8.1.1   Fixed Part..................................... 50
 7.8.1.2   Addresses...................................... 50
 7.8.1.3   Segmentation................................... 50
 7.8.1.4   Options........................................ 50
 7.8.1.5   Data........................................... 50
 7.9   Inactive Network Layer Protocol.................... 51
 7.9.1   Network Layer Protocol Id........................ 51
 7.9.2   Data Field....................................... 51
 7.10   Error Report PDU (ER)............................. 52
 7.10.1   Structure....................................... 52
 7.10.1.1   Fixed Part.................................... 53
 7.10.1.2   Addresses..................................... 53
 7.10.1.3   Segmentation.................................. 53
 7.10.1.4   Options....................................... 54
 7.10.1.5   Reason for Discard............................ 54
 7.10.1.6   Error Report Data Field....................... 55

 8   FORMAL DESCRIPTION................................... 56
 8.1   Values of the State Variable....................... 57
 8.2   Atomic Events...................................... 57
 8.2.1   N.UNITDATA_request and N.UNITDATA_indication..... 57
 8.2.2   SN.UNITDATA_request and SN.UNITDATA_indication... 58
 8.2.3   TIMER Atomic Events.............................. 59
 8.3   Operation of the Finite State Automation........... 59
 8.3.1   Type and Constant Definitions.................... 61
 8.3.2   Interface Definitions............................ 65
 8.3.3   Formal Machine Definition........................ 67

 9   CONFORMANCE.......................................... 84
 9.1   Provision of Functions for Conformance............. 84

INTRODUCTION

Okay so this Protocol is one of a whole family of International Standards made to help open systems interconnect โœจ The set covers the services and protocols needed to make that happen ๐ŸŒˆ

This Protocol Standard sits in the layered world defined by the Reference Model for Open Systems Interconnection (ISO 7498) ๐Ÿงš Specifically, it's a protocol of the Network Layer ๐Ÿ’œ It's a Subnetwork Independent Convergence Protocol, combined with relay and routing functions as described in the Internal Organization of the Network Layer (ISO iiii) ๐Ÿฆ‹ It provides the connectionless-mode Network Service defined in ISO 8348/DAD1, Addendum to the Network Service Definition Covering Connectionless-mode Transmission, between Network Service users and/or Network Layer relay systems ๐Ÿ’–

Here's how these standards fit together, per Figure 0-1 ๐ŸŽ€

      ______________OSI Network Service Definition______________
                    |                             ^
                                                  |
                    |                             |
         Protocol     Reference to aims __________|
                    |

      Specification | Reference to assumptions ___
                                                  |
                    |                             |
                                                  |
                    |                             |
                                                  |
                    |                             v
      ______________Subnetwork Service Definition(s) ___________

              Figure 0-1.  Interrelationship of Standards

1. SCOPE AND FIELD OF APPLICATION ๐ŸŒธ

This International Standard is the protocol that gives you the Connectionless-mode Network Service described in ISO 8348/DAD1, Addendum to the Network Service Definition Covering Connectionless-mode Transmission ๐Ÿ’… The protocol relies on a connectionless-mode subnetwork service being there to back it up โœจ

This Standard specifies:

  • a) procedures for the connectionless transmission of data and control information from one network-entity to a peer network-entity;
  • b) the encoding of the protocol data units used for the transmission of data and control information, comprising a variable-length protocol header format;
  • c) procedures for the correct interpretation of protocol control information; and
  • d) the functional requirements for implementations claiming conformance to the Standard.

The procedures are defined in terms of:

  • a) the interactions among peer network-entities through the exchange of protocol data units;
  • b) the interactions between a network-entity and a Network Service user through the exchange of Network Service primitives; and
  • c) the interactions between a network-entity and a subnetwork service provider through the exchange of subnetwork service primitives.

2. REFERENCES ๐Ÿ“š

Here's the reading list, bestie, every single entry ๐Ÿซถ

ISO 7498       Information Processing Systems - Open Systems
               Interconnection - Basic Reference Model

DP 8524        Information Processing Systems - Open Systems
               Interconnection - Addendum to ISO 7498 Covering
               Connectionless-Mode Transmission

DIS 8348       Information Processing Systems - Data Communications -
               Network Service Definition

ISO 8348/DAD1  Information Processing Systems - Data Communications -
               Addendum to the Network Service Definition Covering
               Connectionless-Mode Transmission

ISO 8348/DAD2  Information Processing Systems - Data Communications -
               Addendum to the Network Service Definition Covering
               Network Layer Addressing

DP iiii        Information Processing Systems - Data Communications -
               Internal Organization of the Network Layer

DP 8509        Information Processing Systems - Open Systems
               Interconnection - Service Conventions

ISO TC97/SC16  A Formal Description Technique based on an N1825
               Extended State Transition Model

SECTION ONE. GENERAL โœจ

part 1 of 14, more parts coming bestie ๐Ÿงš๐Ÿ’–

3 DEFINITIONS โœจ

3.1 Reference Model Definitions

okay so first up, we're borrowing a bunch of concepts from ISO 7498 ๐Ÿงš this doc uses them as-is:

   a) Network layer
   b) Network service
   c) Network service access point
   d) network service access point address
   e) Network entity
   f) Routing
   f) Service
   h) Network protocol
   i) Network relay
   j) Network protocol data unit
   k) End system

3.2 Service Conventions Definitions

next, the OSI Service Conventions (ISO 8509) ๐Ÿ’… we're pulling two more from there:

   l) Service user
   m) Service provider

3.3 Network Layer Architecture Definitions

this bit comes from the Internal Organization of the Network Layer (ISO iiii) ๐ŸŒธ and it's all about how the layer is built:

   n) Subnetwork
   o) Relay system
   p) Intermediate system
   q) Subnetwork service

3.4 Network Layer Addressing Definitions

bestie, the addressing stuff is from DIS 8348/DAD2, Addendum to the Network Service Definition Covering Network layer addressing ๐Ÿฆ‹ it's the whole addressing vibe:

   r) Network entity title
   s) Network protocol address information
   t) Subnetwork address
   u) Domain

3.5 Additional Definitions

and now the extra definitions that this document defines for itself ๐Ÿ’– these apply for the purposes of this document only, so read them like they're the official dictionary for this particular doc:

   a) automaton    -  a machine designed to follow automatically a
                      predetermined sequence of operations or to respond
                      to encoded instructions.

   b) local matter -  a decision made by a system concerning its
                      behavior in the Network Layer that is not subject
                      to the requirements of this Protocol.

   c) segment      -  part of the user data provided in the N_UNITDATA
                      request and delivered in the N_UNITDATA
                      indication.

   d) initial PDU  -  a protocol data unit carrying the whole of the
                      user data from an N_UNITDATA request.

   e) derived PDU  -  a  protocol data unit whose fields are identical
                      to those of an initial PDU, except that it carries
                      only a segment of the user data from an N_UNITDATA
                      request.

   f) segmentation -  the act of generating two or more derived PDUS
                      from an initial or derived PDU.  The derived PDUs
                      together carry the entire user data of the initial
                      or derived PDU from which they were generated.
                      [Note: it is possible that such an initial PDU
                      will never actually be generated for a particular
                      N_UNITDATA request, owing to the immediate
                      application of segmentation.]

   g) reassembly   -  the act of regenerating an initial PDU (in order
                      to issue an N_UNITDATA indication) from two or
                      more derived PDUs produced by segmentation.

4 SYMBOLS AND ABBREVIATIONS โœจ

okay the next section is basically an acronym cheat sheet, and honestly it's giving very organised ๐Ÿ—‚๏ธ we've got it all split up by category so you can find stuff fast.

4.1 Data Units

  PDU          Protocol Data Unit
  NSDU         Network Service Data Unit
  SNSDU        Subnetwork Service Data Unit

4.2 Protocol Data Units

  DT PDU       Data Protocol Data Unit
  ER PDU       Error Report Protocol Data Unit

4.3 Protocol Data Unit Fields

this one is the big list of fields, and it's very long, so pace yourself ๐Ÿซถ

  NPID         Network Layer Protocol Identifier
  LI           Length Indicator
  V/P          Version/protocol Identifier Extension
  LT           Lifetime
  SP           Segmentation Permitted Flag
  MS           More Segments Flag
  E/R          Error Report Flag
  TP           Type
  SL           Segment Length
  CS           Checksum
  DAL          Destination Address Length
  DA           Destination Address
  SAL          Source Address Length
  SA           Source Address
  DUID         Data Unit Identifier
  SO           Segment Offset
  TL           Total Length

4.4 Parameters

  DA           Destination Address
  SA           Source Address
  QOS          Quality of Service

4.5 Miscellaneous

and last but not least, the misc pile ๐Ÿ’œ a few of these are the convergence and access protocols you'll keep seeing around:

  SNICP        Subnetwork Independent Convergence Protocol
  SNDCP        Subnetwork Dependent Convergence Protocol
  SNAcP        Subnetwork Access Protocol
  SN           Subnetwork
  P            Protocol
  NSAP         Network Service Access Point
  SNSAP        Subnetwork Service Access Point
  NPAI         Network Protocol Address Information
  NS           Network Service

5. OVERVIEW OF THE PROTOCOL โœจ

Okay bestie, this is where we get the big-picture tour ๐Ÿฆ‹ Let's go!

5.1. Internal Organization of the Network Layer

The whole architecture of the Network Layer lives in its own separate doc, Internal Organization of the Network Layer (ISO iiii) ๐Ÿ’… That doc defines an OSI Network Layer structure and also gives a way to sort protocols so we can slowly progress toward that structure ๐ŸŒธ This protocol is built for the internetworking approach from that doc, working between Network Service users and/or Network Layer relay systems. ngl it's giving modular ๐Ÿงฉ Basically, this protocol is a Subnetwork Independent Convergence Protocol combined with relay and routing functions, so existing network standards can plug right into the OSI framework ๐Ÿ’–

Okay so a Subnetwork Independent Convergence Protocol is one that can be defined without caring about any particular subnetwork ๐Ÿฆ‹ It's needed to make the OSI Connectionless-mode Network Service look the same everywhere between Network Service users and/or Network Layer relay systems, even across a bunch of interconnected subnetworks that are all the same or all different ๐ŸŒˆ This protocol is defined in that subnetwork-independent way on purpose, so there's less variation to deal with when the subnetwork-dependent and/or subnetwork access protocols don't provide the OSI Network Service ๐Ÿซถ

The subnetwork service that the lower sublayers need to give this protocol is listed in Section 5.5 โœจ

5.2. Subsets of the Protocol

Two proper subsets of the full protocol are also defined ๐ŸŽ€ They let you use known subnetwork characteristics, so they're not subnetwork independent (and that's totally fine, it's a trade-off ๐Ÿ’…)

Subset number one is for when you know the source and destination end-systems are hooked up to a single subnetwork ๐Ÿ’œ It's called the "Inactive Network Layer Protocol" subset, which is honestly a very funny name ๐Ÿ’€ Subset number two lets you simplify the header when you know the source and destination end-systems are connected by subnetworks whose subnetwork service data unit (SNSDU) sizes are greater than or equal to a known bound. That bound has to be big enough that segmentation isn't needed ๐Ÿ“ You pick this subset by setting the "segmentation permitted" flag to zero, and it's called the "non-segmenting" protocol subset ๐ŸŒธ

5.3. Addressing

The Source Address and Destination Address parameters mentioned in Section 7.3 of this International Standard are OSI Network Service Access Point Addresses ๐Ÿฆ‹ The syntax and semantics of an OSI Network Service Access Point Address, the syntax and encoding of the Network Protocol Address Information this protocol uses, and the relationship between the NSAP and the NPAI are all described in a separate doc: ISO 8348/DAD2, Addendum to the Network Service Definition covering Network Layer Addressing ๐Ÿ“š

The syntax and semantics of the titles and addresses used for relaying and routing are also described in ISO 8348/DAD2 โœจ

5.4. Service Provided by the Network Layer

The service this protocol gives you is a connectionless-mode Network Service ๐Ÿ’– That service is described in ISO 8348/DAD1, Addendum to the Network Service Definition Covering Connectionless-mode Transmission. Here are the Network Service primitives it provides, summed up for you ๐Ÿ‘‘

               Primitives                Parameters
    +--------------------------------------------------------+
    |                           |                            |
    | N_UNITDATA Request        | NS_Destination_Address,    |
    |            Indication     | NS_Source_Address,         |
    |                           | NS_Quality_of_Service,     |
    |                           | NS_Userdata                |
    +--------------------------------------------------------+

               Table 5-1.  Network Service Primitives

Okay, the Addendum to the Network Service Definition Covering Connectionless-mode Transmission (ISO 8348/DAD1) says a connectionless-mode Network-service-data-unit can be at most 64512 octets ๐Ÿ™ˆ That's a big boy size ๐Ÿ’…

5.5. Service Assumed from the Subnetwork Service provider

The subnetwork service this protocol needs is made up of these primitives ๐Ÿงš

              Primitives                  Parameters
    +--------------------------------------------------------+
    |                           |                            |
    | SN_UNITDATA Request       | SN_Destination_Address,    |
    |             Indication    | SN_Source_Address,         |
    |                           | SN_Quality_of_Service,     |
    |                           | SN_Userdata                |
    +--------------------------------------------------------+

             Table 5-2.  Subnetwork Service Primitives

5.5.1. Subnetwork Addresses

The source and destination addresses point to the points of attachment to a public or private subnetwork (or subnetworks) involved in the transmission ๐ŸŒˆ The syntax and semantics of subnetwork addresses come from the Service Definition of each individual subnetwork, not from this Protocol Standard, so this protocol doesn't define them ๐Ÿซถ

5.5.2. Subnetwork Quality of Service

Subnetwork Quality of Service describes the bits of a subnetwork connectionless-mode service that are down to the subnetwork service provider alone ๐Ÿ’…

Each subnetwork connectionless-mode transmission comes with some quality of service measures that get requested when the primitive action starts ๐Ÿฆ‹ These requested measures (parameter values and options) are based on the Network Service provider already knowing what the subnetwork offers ๐Ÿง  That knowledge usually gets collected before the subnetwork connectionless-mode service is invoked, so it's not a surprise ๐ŸŽ€

Note: The quality of service parameters identified for the subnetwork connectionless-mode service MAY in some circumstances be directly derivable from or mappable onto those identified in the connectionless-mode Network Service; e.g., the parameters - a) transit delay; - b) protection against unauthorized access; - c) cost determinants; - d) priority; and - e) residual error probability as defined in ISO 8348/DAD1, Addendum to the Network Service Definition Covering Connectionless-mode Transmission, MAY be employed. For those subnetworks which do not inherently provide Quality of Service as a parameter when the primitive action is initiated, it is a local matter as to how the semantics of the service requested might be preserved. In particular, there MAY be instances in which the Quality of Service requested cannot be maintained. In such circumstances, the subnetwork service provider SHALL attempt to deliver the protocol data unit at whatever Quality of Service is available.

5.5.3. Subnetwork User Data

The SN_Userdata is an ordered multiple of octets, and it gets transferred transparently between the specified subnetwork service access points ๐Ÿ“

The subnetwork service is REQUIRED to support a subnetwork service data unit size of at least the maximum size of the Data PDU header plus one octet of NS-Userdata ๐Ÿ’œ That works out to a minimum subnetwork service data unit size of 256 octets ๐ŸŒธ

Where the subnetwork service can support an SNSDU size bigger than the Data PDU header plus one octet of NS_Userdata, the protocol MAY take advantage of that ๐Ÿš€ Specifically, if every SNSDU size of the subnetworks involved is known to be big enough that segmentation isn't required, then the "non-segmenting" protocol subset MAY be used ๐ŸŽ€

5.5.4. Subnetwork Dependent Convergence Functions

Subnetwork Dependent Convergence Functions MAY be performed to provide a connectionless-mode subnetwork service when the subnetworks also provide a connection-oriented subnetwork service ๐Ÿ’… If a subnetwork provides a connection-oriented service, some subnetwork dependent function is assumed to map it onto the required subnetwork service we just talked about ๐Ÿฆ‹

A Subnetwork Dependent Convergence Protocol MAY also be employed in cases where the functions assumed from the subnetwork service provider aren't being performed โœจ

5.6. Service Assumed from Local Evironment

A timer service is provided so the protocol entity can schedule events โฐ

There are three primitives for the S_TIMER service ๐Ÿซถ

  1. the S-TIMER request;
  2. the S_TIMER response; and
  3. the S_TIMER cancel.

The S_TIMER request primitive tells the local environment to start a timer with the specified name and subscript, and to keep it going for the duration given by the time parameter โณ

The S_TIMER response primitive comes from the local environment to say the delay asked for by the matching S_TIMER request has elapsed ๐Ÿ””

The S_TIMER cancel primitive is a heads-up to the local environment that the specified timer(s) SHOULD be cancelled ๐Ÿ™…โ€โ™€๏ธ If the subscript parameter isn't specified, then every timer with that name gets cancelled. Otherwise, only the timer with that name and subscript gets cancelled. If no timers match the parameters you gave, the local environment takes no action ๐ŸŒˆ

The parameters of the S_TIMER service primitives are:

          Primitives                  Parameters
    +--------------------------------------------------------+
    |                           |                            |
    | S_TIMER Request           | S_Time                     |
    |                           | S_Name                     |
    |                           | S_Subscript                |
    |                           |                            |
    | S_TIMER Response          | S_Name                     |
    |         Cancel            | S_Subscript                |
    +--------------------------------------------------------+

                    Table 5-3.  Timer Primitives

The time parameter gives the duration of the specified timer โŒ› A timer gets an identifying label through the name parameter ๐Ÿท๏ธ The subscript parameter is a value that tells apart timers with the same name. Put the name and subscript together and you get a unique reference to the timer ๐Ÿ”‘


SECTION TWO. SPECIFICATION OF THE PROTOCOL ๐Ÿ‘‘

6. PROTOCOL FUNCTIONS

This section describes the functions this Protocol performs ๐Ÿ› ๏ธ

Not all of the functions MUST be performed by every implementation ๐Ÿ™Œ Section 6.17 tells you which functions MAY be omitted, and what the correct behavior is when requested functions aren't implemented ๐Ÿ’…

6.1. PDU Composition Function

This function builds a protocol data unit following the rules in Section 7 ๐Ÿงฑ The Protocol Control Information needed to deliver the data unit to its destination comes from the current state information and from the parameters given with the N_UNITDATA Request, like source and destination addresses, QOS, and so on ๐Ÿ“ฆ The user data passed in from the Network Service user in the N_UNITDATA Request becomes the Data field of the protocol data unit ๐Ÿ’œ

While the protocol data unit is being composed, a Data Unit Identifier gets assigned to uniquely identify all the segments of the matching NS_Userdata ๐Ÿ†” The "Reassemble PDU" function treats PDUs as belonging to the same Initial PDU, and so the same N_UNITDATA request, if they share the same Source and Destination Addresses and Data Unit Identifier ๐Ÿงฉ That's the whole vibe ๐Ÿซถ

Okay bestie, the Data Unit Identifier is the PDU's little ID tag ๐ŸŽ€ It's there for ancillary stuff like error reporting, and the originator MUST choose it so it stays unique for that Source and Destination Address pair for the whole maximum lifetime of the PDU (and any Derived PDUs) in the network ๐Ÿ”ฅ

During composition, the originator works out the total length of the PDU and drops it into the Total Length field of the header ๐Ÿ“ That field never changes in any Derived PDU for the whole lifetime of the protocol data unit. Iconic consistency ๐Ÿ’…

When the non-segmenting subset is in use, there's no Total Length field and no Data Unit Identifier field ๐Ÿ™ˆ Instead, the originator puts the PDU's total length in the Segment Length field, and that one stays the same for the PDU's whole lifetime โœจ

6.2 PDU Decomposition Function

This function strips the Protocol Control Information off the protocol data unit ๐Ÿงš While it does that, it holds on to the info needed to build the N_UNITDATA Indication. The data field of the received PDU is kept around until every segment of the original service data unit has arrived. That's the NS_Userdata parameter of the N_UNITDATA Indication, bestie ๐Ÿ’–

6.3 Header Format Analysis Function

This function figures out whether the full Protocol from this Standard is being used, or one of its defined proper subsets ๐ŸŒˆ If the PDU's Network Layer Protocol Identifier says it's a standard version of the Protocol, this function checks whether the destination address in the PDU matches an NSAP served by this network-entity. If it does, the PDU has reached its destination. If not, it MUST be forwarded ๐Ÿฆ‹

If the Network Layer Protocol Identifier says the Inactive Network Layer Protocol subset is in use, then there's no more header analysis needed ๐ŸŒธ In that case, the network-entity just decides one of two things: either the network address inside the supporting subnetwork protocol's address info matches a network Service Access Point address served by this network-entity, or something went wrong and an error happened ๐Ÿ˜ญ If the subnetwork PDU got delivered correctly, the protocol data unit MAY be decomposed using the procedure for that specific subnetwork protocol โœจ

6.4 PDU Lifetime Control Function

This function enforces the maximum PDU lifetime โณ It's basically best friends with the "Header Format Analysis" function. It checks whether a received PDU can keep being forwarded, or whether its lifetime has run out. If the lifetime is up, the PDU MUST be discarded ๐Ÿ’€

The Lifetime Control function depends on the Lifetime field in the header. At any moment, that field holds the PDU's remaining lifetime, counted in units of 500 milliseconds โฑ๏ธ The originating network-entity sets the Lifetime of the Initial PDU and puts it in the Lifetime field.

6.5 Route PDU Function

This function picks the network-entity that a protocol data unit should be forwarded to ๐Ÿ—บ๏ธ It uses the destination NSAP address parameters, the Quality of Service parameter, and/or other parameters to decide. It also figures out which subnetwork has to be crossed to get to that network-entity. If segmentation happens, it further decides which subnetwork(s) the segments may cross to reach that network-entity ๐Ÿš‡

6.6 Forward PDU Function

This function sends a subnetwork service primitive (see Section 5.5) to the subnetwork that the "Route PDU" function picked ๐Ÿ“จ It hands over the PDU as an SNSDU, plus whatever address info that subnetwork needs to identify the "next" intermediate-system within its own address domain ๐ŸŽฏ

When an Error Report PDU is about to be forwarded and it's longer than the maximum user data the subnetwork accepts, it SHALL be truncated to the maximum acceptable length and forwarded with no other change ๐Ÿซถ When a Data PDU is about to be forwarded and it's longer than the maximum user data the subnetwork accepts, the Segmentation function gets applied (see Section 6.7, which follows) โœ‚๏ธ

6.7 Segmentation Function

Segmentation happens when the protocol data unit is bigger than the maximum size of the user data parameter field in the subnetwork service primitive ๐Ÿ“

Segmentation means composing two or more new PDUs (Derived PDUs) from the PDU you received. The received PDU MAY be the Initial PDU, or it MAY be a Derived PDU ๐Ÿ‘‘ Every PDU derived from the Initial PDU gets its own copy of the Protocol Control Information needed to identify, route, and forward it. The user data inside the received PDU gets split up so each Derived PDU fits the user data parameter field of the subnetwork service primitive ๐Ÿ’œ

Derived PDUs count as coming from the same Initial PDU when they share:

  • a) the source address,
  • b) the destination address, and
  • c) the data unit identifier.

These fields in the PDU header are used together with the Segmentation function ๐Ÿฆ‹

  • a) Segment Offset: says which octet in the Initial PDU's data field the segment starts at.
  • b) Segment Length: gives the number of octets in the Derived PDU, header and data included.
  • c) More Segments Flag: set to one if this Derived PDU doesn't contain, as its last octet of user data, the final octet of the Initial PDU.
  • d) Total Length: gives the entire length of the Initial PDU, header and data included.

Derived PDUs MAY be segmented again, and that doesn't restrict how the individual Derived PDUs get routed ๐ŸŒˆ

The Segmentation Permitted flag gets set to one when segmentation is allowed. If the Initial PDU is never going to be segmented anywhere during its lifetime in the network, the flag gets set to zero ๐Ÿ™…โ€โ™€๏ธ

When the Segmentation Permitted flag is zero, the non-segmenting protocol subset is in use โœจ

6.8 Reassembly Function

The Reassembly Function rebuilds the Initial PDU that was sent to the destination network-entity out of the Derived PDUs created during the Initial PDU's lifetime ๐Ÿงฉ

There's a time limit on how long segments (Derived PDUs) of an Initial PDU get held at a reassembly point โฐ That way, resources can be freed once no more segments of the Initial PDU are expected to show up at that point. When that happens, the segments (Derived PDUs) of the Initial PDU held at the reassembly point get discarded, their resources get freed, and, if it's been selected, an Error Report is generated ๐Ÿซ 

Note: The Segmentation and Reassembly functions are mainly designed so that reassembly happens at the destination ๐Ÿ’… Other schemes that are not ruled out include ones that: - a) interact with the routing algorithm to favor paths where fewer segments get generated, - b) generate more segments than strictly necessary, so that extra segmentation can be avoided at some later point, or - c) allow partial or full reassembly at some point along the route where it's known that the subnetwork with the smallest PDU size has been crossed. The info needed to use one of these alternative strategies MAY be made available through a Network Layer Management function ๐Ÿ”ฅ How the reassembly lifetime relates to the PDU lifetime is a local matter ๐Ÿ™ƒ However, the reassembly algorithm MUST preserve the intent of the PDU lifetime. So the reassembly function MUST discard any PDUs whose lifetime would otherwise have expired if they hadn't been under its control โณ

6.9 Discard PDU Function

This function does all the cleanup needed to free the resources the network-entity reserved, in any of these situations (fair warning, the list isn't exhaustive ๐Ÿ‘€):

  • a) A violation of protocol procedure has occurred.
  • b) A PDU is received whose checksum doesn't match its contents.
  • c) A PDU is received, but because of congestion it can't be processed.
  • d) A PDU is received whose header can't be analyzed.
  • e) A PDU is received that can't be segmented and can't be forwarded because its length goes over the maximum subnetwork service data unit size.
  • f) A PDU is received whose destination address is unreachable or unknown.
  • g) Incorrect or invalid source routing was specified. This could be a syntax error in the source routing field, an unknown or unreachable address in the source routing field, or a path that isn't acceptable for other reasons.
  • h) A PDU is received whose PDU lifetime has expired, or the lifetime expires during reassembly.
  • i) A PDU is received that contains an unsupported option.

6.10 Error Reporting Function

6.10.1 Overview

This function sends an Error Report PDU back to the source network-entity whenever a protocol data unit gets discarded ๐Ÿ“ฃ The source network-entity sets an "error report flag" in the original PDU to say whether Error Report PDUs should come back or not ๐Ÿ’Œ

The Error Report PDU names the discarded PDU, says what kind of error was detected, and says where the error was detected. Part or all of the discarded PDU goes into the data field of the Error Report PDU ๐ŸŽ

The originator's address of the Data Protocol Data Unit goes in two places: it's the destination address of the Error Report PDU, and it's also the source address of the original Data PDU, which lives in the Data field of the Error Report PDU ๐Ÿซถ The originator's address for the Error Report PDU itself sits in the source address field of its header ๐Ÿง 

Note: Not getting an Error Report PDU does not mean the PDU sent by a source network-entity was delivered correctly ๐Ÿ˜ฌ

6.10.2 Requirements

An Error Report PDU SHALL NOT be generated to report the discarding of a PDU that itself contains an Error Report ๐Ÿšซ

An Error Report PDU SHALL NOT be generated when a PDU is discarded, unless that PDU has the Error Report flag set to allow Error Reports ๐Ÿ™…โ€โ™€๏ธ

If a Data PDU is discarded and has the Error Report flag set to allow Error Reports, an Error Report PDU SHALL be generated if the reason for the discard (see Section 6.9) is:

  • a) destination address unreachable,
  • b) source routing failure,
  • c) unsupported options, or
  • d) protocol violation.
Note: This list SHALL include all nontransient reasons for discard ๐Ÿง It may therefore need to be amended or extended if the definitions of those reasons change.

If a Data PDU with the Error Report flag set to allow Error Reports is discarded for any other reason, an Error Report PDU MAY be generated (as an implementation option) โœจ

6.10.3 Processing of Error Reports

Okay so Error Report PDUs get forwarded by intermediate network-entities exactly the same way Data PDUs do ๐Ÿš€ no VIP treatment, bestie. ๐Ÿ’… But here's the tea: an Error Report PDU could end up longer than the maximum user data size of some subnetwork it has to cross on the way back to the origin of the discarded PDU ๐Ÿ˜ญ When that happens, the Forward PDU function SHALL truncate the PDU to the maximum size acceptable.

The entire header of the discarded data unit SHALL be included in the data field of the Error Report PDU. Some or all of the data field of the discarded data unit MAY also be included โœจ

Note: Since the originating network-entity controls suppression of Error Report PDUs (not the NS User), the originator SHOULD be careful when suppressing ER PDUs. You don't want error reporting switched off for every PDU that gets generated ๐Ÿ™ˆ

6.11. PDU Header Error Detection ๐Ÿ›ก๏ธ

The PDU Header Error Detection function protects against failure of intermediate or end-system network-entities caused by processing erroneous information in the PDU header. It works with a checksum computed on the PDU header, and that checksum gets verified at each point where the header is processed. If PDU header fields are modified (for example, by the lifetime function), the checksum is modified too, so it stays valid ๐Ÿงฎ

An intermediate system network-entity MUST NOT recompute the checksum for the entire header, even if fields are modified.

Note: This is so that an inadvertent modification of a header while a PDU is being processed by an intermediate system (for example, due to a memory fault) may still be detected by the PDU Header Error function. Smart, right? ๐Ÿง 

The use of this function is OPTIONAL, and it is selected by the originating network-entity. If the function is not used, the checksum field of the PDU header is set to zero.

If the function is selected by the originating network-entity, the value of the checksum field causes the following formulae to be satisfied:

     L
   (SUM)     a   = 0  (modulo 255)
              i
     i=1

     L
   (SUM)     (L-i+1) a   = 0 (modulo 255)
                       i
     i=1

    Where L = the number of octets in the PDU header, and
          a = value of octet at position i.
           i

When the function is in use, neither octet of the checksum field MUST NOT be set to zero ๐Ÿšซ0๏ธโƒฃ

Annex C contains descriptions of algorithms that MAY be used to calculate the correct value of the checksum field when the PDU is created, and to update the checksum field when the header is modified ๐Ÿ“–

6.12. Padding Function ๐Ÿซง

The padding function lets you reserve space in the PDU header that doesn't support any other function. Octet alignment MUST be maintained.

Note: An example of this function is causing the data field of a PDU to begin on a convenient boundary for the originating network-entity, such as a computer word boundary ๐Ÿ’ป

6.13. Security ๐Ÿ”

Protecting information flowing between transport-entities is a big deal ๐Ÿ‘€ A system may wish to control the distribution of secure data by assigning levels of security to PDUs. As a local consideration, the Network Service user could be authenticated to check whether they have permission to communicate at a particular security level before sending the PDU. No protocol exchange is required for the authentication process, but the OPTIONAL security parameter in the options part of the PDU header MAY be used to convey the particular security level between peer network-entities ๐Ÿค

The syntax and semantics of the security parameter are not specified by this Standard. The security parameter relates to the "protection from unauthorized access" Quality of service parameter described in ISO 8348/DAD1, Addendum to the Network Service Definition Covering Connectionless-mode Transmission. To help interoperation between end-systems and relay-systems, and to avoid different interpretations of the same encoding, a mechanism is provided to tell user-defined security encoding apart from standardized security encoding ๐Ÿซถ

6.14. Source Routing Function ๐Ÿ—บ๏ธ

The Source Routing function lets the originator specify the path a generated PDU must take. Source routing can only be selected by the originator of a PDU. Source Routing is done using a list of intermediate system addresses (or titles, see Section 5.3 and 5.5.1) held in a parameter within the options part of the PDU Header. The size of the option field is determined by the originating network-entity. The length of this option does not change as the PDU traverses the network. Attached to this list is an indicator that identifies the next entry to be used. This indicator is advanced by the receiver of the PDU when the next address matches its own address. The indicator is updated as the PDU is forwarded, so it always points at the right entry at each stage of relaying ๐Ÿฆ‹

Two forms of the source routing option are provided. The first form, called complete source routing, requires that the specified path MUST be taken. If the specified path cannot be taken, the PDU MUST be discarded. The source MAY be informed of the discard using the Error Reporting function described in Section 6.10 ๐Ÿ“ฌ

The second form is called partial source routing. Again, each address in the list MUST be visited in the order specified while on route to the destination. However, with this form, the PDU MAY take any path necessary to arrive at the next address in the list. The PDU will not be discarded (for source routing related causes) unless one of the addresses specified cannot be reached by any available route ๐Ÿงญ

6.15. Record Route Function ๐Ÿ“

The Record Route function permits the exact recording of the paths taken by a PDU as it traverses a series of interconnected subnetworks. A recorded route is a list of intermediate system addresses held in a parameter within the options part of the PDU header. The size of the option field is determined by the originating network-entity. The length of this option does not change as the PDU traverses the network.

The list is built as the PDU traverses a set of interconnected subnetworks. Only intermediate system addresses go in the recorded route. The address of the originator of the PDU is NOT recorded in the list. When an intermediate system network-entity processes a PDU containing the record route parameter, it inserts its own address (or titles, see Sections 5.3 or 5.5.1) into the list of recorded addresses ๐ŸŒธ

The record route option contains an indicator that identifies the next available octet for recording the route. This identifier is updated as entries are added to the list. If adding the current address to the list would exceed the size of the option field, the indicator is set to show that recording of the route has terminated. The PDU MAY still be forwarded to its final destination, without any further addition of intermediate system addresses.

Note: The Record Route function is mainly meant for diagnosing network problems. Its mechanism was designed with that in mind, and may provide a return path ๐Ÿ”

6.16. Quality of Service Maintenance Function ๐Ÿ’œ

To support the Quality of Service requested by Network Service users, the Protocol may need to make QOS information available at intermediate systems. This information may be used by network entities in intermediate systems to make routing decisions where those decisions affect the overall QOS provided to NS users.

When the QOS indicated cannot be maintained, the NS provider will attempt to deliver the PDU at a QOS lower than the one indicated. The NS provider will not necessarily notify you of a failure to meet the indicated quality of service ๐Ÿ˜ฌ

6.17. Classification of Functions ๐Ÿ—‚๏ธ

Implementations do not have to support all of the functions described in Section 6. Functions are split into three categories:

  • Type 1: These functions MUST be supported.
  • Type 2: These functions MAY or may not be supported. If an implementation does not support a Type 2 function, and the function is selected by a PDU, then the PDU SHALL be discarded, and an Error Report PDU SHALL be generated and forwarded to the originating network-entity, provided that the Error Report flag is set.
  • Type 3: These functions MAY or may not be supported. If an implementation does not support a Type 3 function, and the function is selected by a PDU, then the function is not performed and the PDU is processed exactly as though the function was not selected. The protocol data unit SHALL NOT be discarded.

Table 6-1 shows how the functions are split into these three categories ๐Ÿ“Š

         +---------------------------------------------------+
         | Function                       |  Type            |
         |--------------------------------|------------------|
         |                                |                  |
         | PDU Composition                |  1               |
         | PDU Decomposition              |  1               |
         | Header Format Analysis         |  1               |
         | PDU Lifetime Control           |  1               |
         | Route PDU                      |  1               |
         | Forward PDU                    |  1               |
         | Segment PDU                    |  1               |
         | Reassemble PDU                 |  1               |
         | Discard PDU                    |  1               |
         | Error Reporting                |  1 (note 1)      |
         | PDU Header Error Detection     |  1 (note 1)      |
         | Padding                        |  1 (notes 1   2) |
         | Security                       |  2               |
         | Complete Source Routing        |  2               |
         | Partial Source Routing         |  3               |
         | Priority                       |  3               |
         | Record Route                   |  3               |
         | Quality of Service Maintenance |  3               |
         +---------------------------------------------------+

            Table 6-1.  Categorization of Protocol Functions

Notes:

  1. While the Padding, Error Reporting, and Header Error Detection functions MUST be provided, they are only provided when the sending Network Service user selects them ๐Ÿ™Œ
  2. The correct treatment of the Padding function involves no processing. So this could just as easily be described as a Type 3 function ๐Ÿคทโ€โ™€๏ธ
  3. The reason Type 3 functions are included is that for some functions, it matters more to forward PDUs between intermediate systems or deliver them to an end-system than it does to support the functions. Type 3 functions SHOULD be used where they are advisory in nature, and they SHOULD NOT be the cause of a PDU being discarded when not supported ๐Ÿ’–

7. STRUCTURE AND ENCODING OF PDUS โœจ

7.1. Structure ๐Ÿงฑ

All Protocol Data Units SHALL contain an integral number of octets. The octets in a PDU are numbered starting from one (1) and increasing in the order in which they are put into an SNSDU. The bits in an octet are numbered from one (1) to eight (8), where bit one (1) is the low-order bit ๐Ÿ”ข

When consecutive octets are used to represent a binary number, the lower octet number is the one holding the most significant value ๐Ÿง โœจ So the lowest-numbered octet is basically the main character ๐Ÿ‘‘

Any subnetwork supporting this protocol is REQUIRED to state in its specification how octets get transferred, using the terms "most significant bit" and "least significant bit." ๐Ÿ“œ The PDUs of this protocol are defined using those same two terms ๐Ÿ’…

Note:

When the encoding of a PDU is shown in a diagram in this section, we use this representation:

  • a) octets are shown with the lowest numbered octet on the left, and higher numbered octets further to the right;
  • b) within an octet, bits are shown with bit eight (8) on the left and bit one (1) on the right.

PDUs SHALL contain, in the following order:

  1. the header, comprising:
    • a) the fixed part;
    • b) the address part;
    • c) the segmentation part, if present;
    • d) the options part, if present

and

  1. the data field, if present.

Here's the layout, bestie ๐ŸŽ€

                     Part:                Described in:

          +-------------------+
          |    Fixed Part     |            Section 7.2
          +-------------------+

          +-------------------+
          |   Address Part    |            Section 7.3
          +-------------------+

          +-------------------+
          | Segmentation Part |            Section 7.4
          +-------------------+

          +-------------------+
          |   Options Part    |            Section 7.5
          +-------------------+

          +-------------------+
          |       Data        |            Section 7.6
          +-------------------+

Figure 7-1. PDU Structure ๐Ÿฆ‹


7.2 Fixed Part ๐ŸŒธ

7.2.1 General

The fixed part holds the frequently used parameters, including the type code (DT or ER) of the protocol data unit. ๐Ÿ’– The length and structure of the fixed part are defined by the PDU code.

Here's what the fixed part looks like ๐Ÿ‘€

                                                    Octet
          +------------------------------------+
          | Network Layer Protocol Identifier  |     1
          |------------------------------------|
          |         Length Indicator           |     2
          |------------------------------------|
          |   Version/Protocol Id Extension    |     3
          |------------------------------------|
          |            Lifetime                |     4
          |------------------------------------|
          |S |M |E/R|         Type             |     5
          | P| S|   |                          |
          |------------------------------------|
          |          Segment Length            |    6,7
          |------------------------------------|
          |             Checksum               |    8,9
          +------------------------------------+

Figure 7-2. PDU Header--Fixed Part

7.2.2 Network Layer Protocol Identifier

The value of this field SHALL be binary 1000 0001. ๐Ÿ”ฅ It identifies this Network Layer Protocol as ISO 8473, Protocol for Providing the Connectionless-mode Network Service.

7.2.3 Length Indicator

The length is a binary number with a maximum value of 254 (1111 1110). ๐Ÿ“ It's the length in octets of the header, as described in Section 7.1, Structure. The value 255 (1111 1111) is reserved for possible future extensions ๐Ÿ”ฎ

Note:

The rules for forwarding and segmentation make sure the header length is the same for all segments (Derived PDUs) of the Initial PDU, and it's the same as the header length of the Initial PDU. ๐Ÿงฉ

7.2.4 Version/Protocol Identifier Extension

The value of this field is binary 0000 0001. ๐ŸŒˆ It identifies a standard version of ISO 8473, Protocol for Providing the Connectionless-mode Network Service.

7.2.5 PDU Lifetime

โณ The Lifetime field is a binary number showing the remaining lifetime of the PDU, in units of 500 milliseconds.

The originating network-entity sets the Lifetime field, and every network-entity that processes the PDU decrements it. The PDU SHALL be discarded if the value of the field reaches zero. ๐Ÿ’€

When a network-entity processes a PDU, it decrements the Lifetime by at least one. The Lifetime SHALL be decremented by more than one if the sum of:

  1. the transit delay in the subnetwork from which the PDU was received; and
  2. the delay within the system processing the PDU

exceeds, or is estimated to exceed, 500 milliseconds. In that case, the lifetime field SHOULD be decremented by one for each additional 500 milliseconds of delay. The delay doesn't need to be precise ๐Ÿ™ˆ but where there's an error, the value used SHALL be an overestimate, not an underestimate.

If the Lifetime reaches zero before the PDU reaches the destination, the PDU SHALL be discarded. The Error Reporting function SHALL be invoked, as described in Section 6.10, Error Reporting Function, and it MAY result in the generation of an ER PDU. Whether the destination network-entity performs the Lifetime Control function is a local matter. ๐Ÿ 

When the Segmentation function is applied to a PDU, the Lifetime field is copied into all of the Derived PDUs. ๐Ÿฆ‹

7.2.6 Flags

7.2.6.1 Segmentation Permitted and More Segments Flags

The Segmentation Permitted flag decides whether segmentation is allowed. A value of one means segmentation is permitted โœจ

A value of zero means the non-segmenting protocol subset is being used. In that case, the segmentation part of the PDU header is not present, and the Segment Length field does double duty as the Total Length field ๐ŸŽ€

The More Segments flag tells you whether the data segment in this PDU contains (as its last octet) the last octet of the User Data in the NSDU. ๐Ÿ“ฆ When the More Segments flag is set to one (1), segmentation has happened, and the last octet of the NSDU is not in this PDU. The More Segments flag cannot be set to one (1) if the Segmentation Permitted flag isn't set to one (1). ๐Ÿšซ

When the More Segments flag is set to zero (0), the last octet of the Data Part of the PDU is the last octet of the NSDU. ๐Ÿ

7.2.6.2 Error Report Flag

When the Error Report flag is set to one, the rules in Section 6.10 decide whether an Error Report PDU gets generated when the PDU is discarded ๐Ÿ“ฃ

When the Error Report flag is set to zero, discarding the PDU will not cause an Error Report PDU to be generated ๐Ÿคซ

7.2.7 Type Code

The Type code field identifies the type of the protocol data unit. Allowed values are in Table 7-1 ๐Ÿ’…

                              Bits    5 4 3 2 1
                  +-----------------------------+
                  |  DT PDU  |        1 1 1 0 0 |
                  |-----------------------------|
                  |  ER PDU  |        0 0 0 0 1 |
                  +-----------------------------+

Table 7-1. Valid PDU Types

7.2.8 PDU Segment Length

The Segment Length field gives the entire length of the PDU segment, including both header and data (if present). ๐Ÿ“ When the full protocol is used and a PDU isn't segmented, this field's value is the same as the Total Length field in the Segmentation Part of the header.

When the Non-segmenting protocol subset is used, there's no segmentation part in the header. In this subset, the Segment Length field acts as the Total Length field of the header (see Section 7.4.3). ๐Ÿง 

7.2.9 PDU Checksum

The checksum is computed over the entire PDU header ๐Ÿ” That includes the segmentation and options parts, if they're present. A checksum value of zero is reserved to mean "ignore the checksum." The PDU Header Error Detection function makes sure zero is never a valid checksum. A non-zero value means the checksum MUST be processed, or the PDU MUST be discarded. ๐Ÿ’€


7.3 Address Part ๐Ÿงš

7.3.1 General

Address parameters are identified by where they sit, right after the fixed part of the PDU header ๐Ÿ“ Here's the address part:

                                                    Octet
        +--------------------------------------+
        |                                      |
        | Destination Address Length Indicator |      10
        |                                      |
        |--------------------------------------|
        |                                      |      11
        |         Destination Address          |
        |                                      |      m-1
        |--------------------------------------|
        |                                      |
        |   Source Address Length Indicator    |       m
        |                                      |
        |--------------------------------------|
        |                                      |      m+1
        |           Source Address             |
        |                                      |      n-1
        +--------------------------------------+

Figure 7-3. PDU header--Address Part

7.3.1.1 Destination and Source Address Information

The Destination and Source addresses are Network Service Access Point addresses, as defined in ISO 8348/DAD2, Addendum to the Network Service Definition Covering Network Layer Addressing. ๐ŸŒ

The Destination and Source Address information has variable length ๐Ÿ“

The Destination Address Length Indicator field gives the length of the Destination Address in octets. The Destination Address field comes right after the Destination Address Length Indicator field. The Source Address Length Indicator field gives the length of the Source Address in octets, and it follows the Destination Address field. The Source Address field comes right after the Source Address Length Indicator field. ๐Ÿ’ซ

Each address parameter is encoded like this:

                  Bits   8   7   6   5   4   3   2   1
        +---------------------------------------------+
        | Octet  | Address parameter Length Indicator |
        |   n    |           (e.g., 'm')              |
        |---------------------------------------------|
        | Octets |                                    |
        |  n+1   |     Address Parameter Value        |
        | thru   |                                    |
        |  n+m   |                                    |
        +---------------------------------------------+

Table 7-2. Address Parameters


7.4 Segmentation Part ๐ŸŽ€

If the Segmentation Permitted Flag in the Fixed Part of the PDU Header (Octet 4, Bit 8) is set to one, the segmentation part of the header MUST be present. Check it out ๐Ÿ‘‡

                                           Octet
            +------------------------+
            |  Data Unit Identifier  |     n,n+1
            |------------------------|
            |     Segment Offset     |    n+2,n+3
            |------------------------|
            |      Total Length      |    n+4,n+5
            +------------------------+

Figure 7-4. PDU Header--Segmentation Part

When the "Segmentation Permitted" flag is set to zero, the nonsegmenting protocol subset is in use. ๐ŸŒท

7.4.1 Data Unit Identifier

The Data Unit Identifier is how the destination network-entity can put a segmented data unit back together ๐Ÿงฉ. It's two octets, and it identifies the Initial PDU (and therefore its Derived PDUs) so the reassembly actually works. Main character energy ๐Ÿ’…

7.4.2 Segment Offset ๐Ÿฆ‹

For each segment, the Segment Offset field tells you where that segment sits in the data part of the Initial PDU, measured from the start of the data field. The offset is counted in octets, and the first segment's offset is zero ๐ŸŽ€

7.4.3 PDU Total Length ๐Ÿ’œ

The Total Length field gives the entire length of the Initial PDU, header and data included. It's locked in: this field doesn't change in any segment (Derived PDU) for the whole lifetime of the PDU ๐Ÿ”’

7.5 Options Part ๐ŸŒธ

7.5.1 General โœจ

Okay so the options part is where the optional parameters live ๐Ÿงš If it's there, it holds one or more parameters. How many parameters fit is given by the length of the options part, which works out to:

PDU Header Length - (length of fixed part +
                     length of address part +
                     length of segmentation part).

Here's what the options part of the PDU header looks like ๐Ÿ‘€

                                            Octet
                   +--------------------+
                   |                    |       n+6
                   |      Options       |
                   |                    |       p
                   +--------------------+

Figure 7-5. PDU Header--Options Part

Each parameter inside the options part of the PDU header is encoded like this, and honestly it's giving very organized ๐Ÿ“ฆ

                       BITS    8  7  6  5  4  3  2  1
          +------------------------------------------+
          |  Octets  |                               |
          |    n     |  Parameter Code               |
          |------------------------------------------|
          |   n+1    |  Parameter Length (e.g., 'm') |
          |------------------------------------------|
          |   n+2    |  Parameter Value              |
          |  n+m+1   |                               |
          +------------------------------------------+

Table 7-3. Encoding of Parameters

The parameter code is a binary number. Without extensions it gives you up to 255 different parameters ๐Ÿ”ข BUT bits 8 and 7 can't take every value, so the real maximum is a bit lower, as noted below. The code 255 (binary 1111 1111) is saved for possible future extensions of the parameter code, so nobody touches it ๐Ÿšซ

The parameter length field tells you how many octets the parameter value field is. That number is 'm', and its theoretical max is 255. The practical max for 'm' is lower ๐Ÿ“‰ For example, if there's only one parameter in the options part, the parameter code and the length indicator themselves eat two octets. So 'm' is limited to:

 253 - (length of fixed part +
 length of address part +
 length of segmentation part).

Every parameter after that one makes the max for 'm' smaller ๐Ÿ“‰

The parameter value field holds the value of whichever parameter the parameter code names ๐Ÿ’–

No parameter codes use bits 8 and 7 with the value 00. Not one ๐Ÿ™…โ€โ™€๏ธ

Implementations shall accept the parameters defined in the options part in any order. Duplicate options (when they're detected) are not permitted. If a PDU shows up with an option duplicated, it should be treated as a protocol error. The rules for handling protocol errors are in Section 6.10, Error Reporting Function ๐Ÿšจ

Here are the parameters that are permitted in the options part ๐Ÿ’…

7.5.2 Padding ๐Ÿง

The padding parameter is there to make the PDU header a convenient size. It's stretching the header out, basically (See Section 6.12) ๐Ÿ›

Parameter Code:       1100 1100
Parameter Length:     variable
Parameter Value:      any value is allowed

7.5.3 Security ๐Ÿ”

This parameter is user defined. Bestie, it's yours to decide ๐Ÿซถ

Parameter Code:       1100 0101
Parameter Length:     variable
Parameter Value:

So the high order bit of the first octet is the Security Domain bit, S, and it gets read two different ways depending on what it's set to ๐Ÿ‘‘

S=0

 +---------------------------
 | S | User Defined        ----
 +------------------------

S=1

 +---------------------------
 | S | CODE | ORGANIZATION ----
 +------------------------

Where:

  • CODE = This field contains a geographic or non-geographic code to which the option applies.
  • ORGANIZATION = This is a further subdivision of the CODE field and is determined by an administrator of the geographic or non-geographic domain identified by the value of CODE.

7.5.4 Source Routing ๐Ÿ—บ๏ธ

The source routing parameter specifies the route from Source Network Address to Destination Network Address, either completely or partially. It's giving GPS energy ๐Ÿ“

Parameter Code:      1100 1000
Parameter Length:    variable
Parameter Value:     2 octet control information
                     succeeded by a concatenation
                     of ordered address fields
                     (ordered from source to destination)

The first octet of the parameter value is the type code, and it means this:

0000 0001     complete source routing
0000 0000     partial source routing

<all other values reserved>

The second octet tells you the octet offset of the next address to be processed in the list. A value of three (3) means the next address starts right after this control octet. Bigger values just point further along, one octet at a time ๐Ÿ‘ฃ

The third octet is where the intermediate-system address list begins. The list is made of variable length address fields, and the first octet of each field tells you how long the address is that fills the rest of that field ๐Ÿ“

7.5.5 Recording of Route ๐Ÿ“

The recording of route parameter keeps track of the intermediate systems the PDU went through. It's the PDU's travel diary โœˆ๏ธ

Parameter Code:       1100 1011
Parameter Length:     variable
Parameter Value:      two octets control information
                      succeeded  by a concatenation of
                      ordered addresses

The first octet tells you whether recording of route was cut off because the option ran out of space. Here's what it means ๐Ÿ™ƒ

0000 0000     Recording of Route still in progress
1111 1111     Recording of Route terminated

<all other values reserved>

The second octet points at the next octet that can be used to record an address. It's counted from the start of the parameter, so a value of three (3) means the octet right after this one is the next to use ๐Ÿ‘‰

The third octet starts the address list. That list is made of variable length address fields, and the first octet of each field says how long the address in the rest of the field is. New address fields always go at the beginning of the list, i.e., the most recently added field starts in the third octet of the parameter value ๐Ÿฅ‡

7.5.6 Quality of Service Maintenance ๐ŸŽฏ

The Quality of Service parameter carries info about the quality of service the originating Network Service user asked for. At intermediate systems, Network Layer relay entities may (but are not required to) use this info to pick a route, but only when more than one route meets the other routing criteria and those routes are known to differ in Quality of Service (see Section 6.16). It's a tiebreaker, bestie ๐Ÿค

Parameter Code:       1100 0011
Parameter Length:     one octet
Parameter Value:      Bit 8:  transit delay vs. cost
                      Bit 7:  residual error probability vs.
                              transit delay
                      Bit 6:  residual error probability vs.
                              cost
                      Bits 5 thru 0 are not specified.

Bit 8 set to one means that, where possible, routing decisions should favor low transit delay over low cost. A value of 0 means routing decisions should favor low cost over low transit delay ๐Ÿ’ธ

Bit 7 set to one means that, where possible, routing decisions should favor low residual error probability over low transit delay. A value of zero means routing decisions should favor low transit delay over low residual error probability ๐ŸŽข

Bit 6 set to one means that, where possible, routing decisions should favor low residual error probability over low cost. A value of 0 means routing decisions should favor low cost over low residual error probability ๐Ÿ’ฐ

7.6 Priority ๐Ÿšฆ

The priority parameter carries the relative priority of the protocol data unit. Intermediate systems that support this option should use this info when routing and when ordering PDUs for transmission. Priority is EVERYTHING ๐Ÿ‘‘

Parameter Code:       1100 1100
Parameter Length:     one octet
Parameter Value:      0000 0000 - Normal (Default)
                      thru
                      0000 1111 - Highest

Values 0000 0001 through 0000 1111 are for higher priority protocol data units. If an intermediate system doesn't support this option, then all PDUs shall be treated as if the field had the value 0000 0000 ๐Ÿ™ˆ

7.7 Data Part ๐Ÿ“

The Data part of the PDU is an ordered multiple of octets. That's the exact same thing as the ordered multiple of octets specified for the NS_Userdata parameter of the N_UNITDATA Request and Indication primitives, so they match ๐Ÿค Here's the data field:

                                           Octet
                +------------------+
                |                  |      p+1
                |       Data       |
                |                  |       z
                +------------------+

Figure 7-6. PDU header--Data Field

7.8 Data (DT) PDU ๐Ÿ’–

7.8.1 Structure โœจ

The DT PDU has the following format:

                                                  Octet
     +--------------------------------------+
     |  Network Layer Protocol Identifier   |      1
     |--------------------------------------|
     |           Length Indicator           |      2
     |--------------------------------------|
     |   Version/Protocol Id Extension      |      3
     |--------------------------------------|
     |              Lifetime                |      4
     |--------------------------------------|
     |SP|MS|E/R|      Type                  |      5
     |--------------------------------------|
     |           Segment Length             |     6,7
     |--------------------------------------|
     |              Checksum                |     8,9
     |--------------------------------------|
     | Destination Address Length Indicator |     10
     |--------------------------------------|
     |         Destination Address          |     11 through m-1
     |--------------------------------------|
     |    Source Address Length Indicator   |      m
     |--------------------------------------|
     |            Source Address            |     m+1 through n-1
     |--------------------------------------|
     |         Data Unit Identifier         |     n,n+1
     |--------------------------------------|
     |            Segment Offset            |     n+2,n+3
     |--------------------------------------|
     |             Total Length             |     n+4,n+5
     |--------------------------------------|
     |                Options               |     n+6 through p
     |--------------------------------------|
     |                 Data                 |     p+1 through z
     +--------------------------------------+

                     Figure 7-7.  PDU Header Format

Okay so that's the whole PDU header map ๐ŸŽ€ Every field has its own octet slot, and the wiggly m and n and p and z markers just tell you where each field starts and ends. Iconic, honestly ๐Ÿซถ

7.8.1.1 Fixed Part

  1. Network Layer Protocol Identifier: See Section 7.2.2.
  2. Length Indicator: See Section 7.2.3.
  3. Version/Protocol Id Extension: See Section 7.2.4.
  4. Lifetime: See Section 7.2.5.
  5. SP, MS, E/R: See Section 7.2.6.
  6. Type Code: See Section 7.2.7.
  7. Segment Length: See Section 7.2.8.
  8. Checksum: See Section 7.2.9.

7.8.1.2 Addresses

See Section 7.3.

7.8.1.3 Segmentation

See Section 7.4.

7.8.1.4 Options

See Section 7.5.

7.8.1.5 Data

See Section 7.7.

7.9 Inactive Network Layer Protocol

Now the inactive one, which is giving minimalist era ๐ŸŒธ

                                              Octet
            +-----------------------------+
            |  Network Layer Protocol Id  |     1
            |-----------------------------|
            |           Data              |     2 through n
            +-----------------------------+

              Figure 7-9.  Inactive Network Layer Protocol

7.9.1 Network Layer Protocol Id

The value of the Network Layer Protocol Identifier field is binary zero (0000 0000). Just zeros, bestie, that's the whole vibe โœจ

7.9.2 Data Field

See Section 7.7.

The length of the NS_Userdata parameter is constrained to be less than or equal to the value of the length of the SN_Userdata parameter minus one. ๐Ÿ’…

7.10 Error Report PDU (ER)

7.10.1 Structure

This is the Error Report PDU, and ngl it's the drama queen of the bunch ๐Ÿ’€

                                              Octet
     +--------------------------------------+
     |   Network Layer Protocol Identifier  |       1
     |--------------------------------------|
     |           Length Indicator           |       2
     |--------------------------------------|
     |     Version/Protocol Id Extension    |       3
     |--------------------------------------|
     |               Lifetime               |       4
     |--------------------------------------|
     |SP|MS|E/R|       Type                 |       5
     |--------------------------------------|
     |             Segment Length           |      6,7
     |--------------------------------------|
     |                Checksum              |      8,9
     |--------------------------------------|
     | Destination Address Length Indicator |      10
     |--------------------------------------|
     |         Destination Address          |     10 through m-1
     |--------------------------------------|
     |     Source Address Length Indicator  |       m
     |--------------------------------------|
     |             Source Address           |     m+1 through n-1
     |--------------------------------------|
     |          Data Unit Identifier        |     n,n+1
     |--------------------------------------|
     |             Segment Offset           |     n+2,n+3
     |--------------------------------------|
     |              Total Length            |     n+4,n+5
     |--------------------------------------|
     |                Options               |     n+6 through p-1
     |--------------------------------------|
     |           Reason for Discard         |     p through q-1
     |--------------------------------------|
     |       Error Report Data Field        |       z
     +--------------------------------------+

                     Figure 7-10.  Error Report PDU

7.10.1.1 Fixed Part

The fixed part of the Error Report Protocol Data Unit is set as though this is a new (Initial) PDU. So the references point you back to the earlier sections that describe what each fixed-part field is made of ๐Ÿงš

  1. Network Layer Protocol Identifier: See Section 7.2.2.
  2. Length Indicator: See Section 7.2.3.
  3. Version/Protocol Id Extension: See Section 7.2.4.
  4. Lifetime: See Section 7.2.5.
  5. SP, MS, E/R: See Section 7.2.6.
  6. Type Code: See Section 7.2.7.
  7. Segment Length: See Section 7.2.8.
  8. Checksum: See Section 7.2.9.

7.10.1.2 Addresses

See Section 7.3.

The Destination Address specifies the original source of the discarded PDU. The Source Address specifies the intermediate system or end system network-entity initiating the Error Report PDU. So one address is the original sender, and the other is who's reporting the drop ๐Ÿ‘‘

7.10.1.3 Segmentation

See Section 7.4.

7.10.1.4 Options

See Section 7.5.

7.10.1.5 Reason for Discard

This parameter is only valid for the Error Report PDU. It provides a report on the discarded protocol data unit. This is where the tea gets spilled ๐Ÿ“

Parameter Code:

 1100 0001

Parameter Length:

 two octets
 type of error encoded in binary:

  0000 0000:  Reason not specified.
  0000 0001:  Protocol Procedure Error.
              other than below:
  0000 0010:  Incorrect checksum.
  0000 0011:  PDU discarded due to congestion.
  0000 0100:  Header syntax error (header cannot
              be parsed).
  0000 0101:  Segmentation is needed but is not
              permitted.

  1000 xxxx:  Addressing Error:
              0000 0000:  Destination Address
                          Unreachable.
              1000 0001:  Destination Address
                          Unknown.

  1001 xxxx:  Source Routing Error:
              1001 0000:  Unspecified Source
                          Routing error.
              1001 0001:  Syntax error in Source
                          Routing field.
              1001 0010:  Unknown Address in
                          Source Routing field.
              1001 0011:  Path not acceptable.

  1010 xxxx:  Lifetime Expiration:
              1010 0000:  Lifetime expired while
                          data unit in transit.
              1010 0001:  Lifetime expired
                          during reassembly.

  1011 xxxx:  PDU discarded due to unsupported
              option:
              1011 0000:  unsupported option not
                          specified.
              1011 0001:  unsupported padding
                          option.
              1011 0010:  unsupported security
                          option.
              1011 0011:  unsupported source
                          routing option.
              1011 0100:  unsupported recording
                          of route option.
              1011 0101:  unsupported QoS
                          Maintenance option.

The second octet contains a pointer to the field in the associated discarded PDU which caused the error. If no one particular field can be associated with the error, then this field contains the value of zero. So the pointer is basically the "this exact spot is the problem" arrow ๐ŸŽฏ

7.10.1.6 Error Report Data Field

This field provides all or a portion of the discarded PDU. The octets comprising this field contain the rejected or discarded PDU up to and including the octet which caused the rejection/discard. Basically the evidence locker, bestie ๐Ÿ”

8. FORMAL DESCRIPTION โœจ

The operation of the protocol is modelled as a finite state automaton governed by a state variable with three values. The behavior of the automaton is defined with respect to individual independent Protocol Data Units. A transition of the automaton is prompted by the occurrence of an atomic event at one of three interfaces:

  1. an interface to the Transport Layer, defined by the service primitives of the Addendum to the Network Service Definition Covering Connectionless-mode Transmission;
  2. an interface to the subnetwork service provider, defined by the SN_UNITDATA primitive of Section 5.5 of this Standard;
  3. an interface to an implementation-dependent timer function defined by the TIMER primitives described in Section 5.6 of this Standard.

In addition, a transition of the automaton may be prompted by the occurrence of a condition of the automaton. ๐Ÿฆ‹

The atomic events are defined in Section 8.2. The occurrence of an atomic event is not in itself sufficient to cause a transition to take place; other conditions, called "enabling conditions" may also have to be met before a particular transition can take place. Enabling conditions are boolean expressions that depend on the values of parameters associated with the corresponding atomic event (that is, the parameters of some primitive), and on the values of locally maintained variables. So an event alone is not enough, it's giving "you need the whole vibe check" ๐Ÿ’…

More than one enabling condition -- and therefore, more than one possible transition -- may be associated with a single atomic event. In every such case, the enabling conditions are mutually exclusive, so that for any given combination of atomic event and parameter values, only one state transition can take place. No overlapping, no drama, just one outcome ๐ŸŒˆ

Associated with each transition is an action, or "output." Actions consist of changes to the values of local variables and the sequential performance of zero or more functions. The operation of the finite state automaton is completely specified in Section 8.3 by defining the action associated with every possible transition. โญ

8.1 Values of the State Variable

The protocol state variable has three values:

  1. INITIAL: The automaton is created in the INITIAL state. No transition may carry the automaton into the INITIAL state. ๐ŸŒธ
  2. REASSEMBLING: The automaton is in the REASSEMBLING state for the period in which it is assembling PDU segments into a complete PDU. ๐Ÿงฉ
  3. CLOSED: The final state of the automaton is the CLOSED state. When the automaton enters the CLOSED state it ceases to exist. Ghosted, fr fr ๐Ÿ‘ป

8.2 Atomic Events

An atomic event is the transfer of a unit of information across an interface. The description of an atomic event specifies a primitive (such as an N_UNITDATA.Request), and the service boundary at which it is invoked (such as the Network Service boundary). The direction of information flow across the boundary is implied by the definition of each of the primitives. Lowkey the most important vocab in this whole section, so take notes bestie ๐Ÿ“๐Ÿ’œ

8.2.1 N.UNITDATA_request and N.UNITDATA_indication โœจ

okay so these two atomic events ๐Ÿฆ‹ happen right at the Network Service boundary. They're defined by the Addendum to the Network Service Definition Covering Connectionless Data Transmission (ISO 8348/DAD1), so that's where to look for the official details ๐Ÿ’…

   N.UNITDATA_request    (NS Source_Address,
                          NS_Destination_Address,
                          NS_Quality_of_Service,
                          NS_Userdata)

   N.UNITDATA_indication (NS_Source_Address,
                          NS_Destination_Address,
                          NS_Quality_of_Service, NS_Userdata)

the parameters of N.UNITDATA_request and N.UNITDATA_indication are collectively called Network Service Data Unit (NSDUs) ๐Ÿ“ฆโœจ

8.2.2 SN.UNITDATA_request and SN.UNITDATA_indication ๐ŸŒธ

these two happen at the interface between this protocol and a subnetwork service provider ๐Ÿ”Œ they're defined in Section 5.5 of this Standard, so go check there too ๐Ÿซถ

   SN.UNITDATA_request    (SN_Source_Address,
                           SN_Destination_Address,
                           SN_Quality_of_Service,
                           SN_Userdata)

   SN.UNITDATA_indication (SN_Source_Address,
                           SN_Destination_Address,
                           SN_Quality_of_Service,
                           SN_Userdata)

the parameters of the SN_UNITDATA request and SN_UNITDATA Indication are collectively called Subnetwork Service Data Units (SNSDUs) ๐Ÿงš

ngl this bit is the plot twist ๐Ÿ˜ญ the value of SN_Userdata can be either an Initial PDU or a Derived PDU, so keep an eye on which one you're holding ๐Ÿ‘‘

8.2.3 TIMER Atomic Events โฐ

the TIMER atomic events happen at the interface between this protocol and its local environment ๐ŸŒˆ they're defined in Section 5.6 of this Standard, so you know the drill ๐Ÿ’–

    S.TIMER_request  (Time,
                      Name,
                      Subscript)

    S.TIMER_cancel   (Name
                      Subscript)

    S.TIMER_response (Name,
                      Subscript)

8.3 Operation of the Finite State Automation ๐Ÿค–๐Ÿ’œ

okay the automaton is defined using the formal description technique and notation from ISO/TC97/SC16 N1347 ๐ŸŽ€ it's built on an extended finite state transition model and the Pascal programming language, and it leans hard on strong variable typing so there's way less room for confusion when you read the spec ๐Ÿง โœจ

this specification formally describes an abstract machine that provides one instance of the Connectionless-Mode Network Service, using the Protocol For Providing the Connectionless-Mode Network Service ๐Ÿฆ‹ it's worth emphasizing that this formal spec doesn't constrain the internal operation or design of any real implementation at all ๐Ÿ™ˆ for example, the program segments inside the state transitions don't have to show up in an actual implementation, full stop ๐Ÿ’… the whole point of a formal spec is to kill as much ambiguity and vagueness as possible in a protocol standard, and it's iconic for that ๐Ÿ‘‘

the formal spec here describes the behavior of one finite-state machine, which handles the protocol behavior for one independent service request ๐ŸŒธ any real implementation is expected to handle many simultaneous finite state machines at once, so it's giving multitasking queen energy ๐Ÿ”ฅ

8.3.1 Type and Constant Definitions ๐Ÿ“

the constants and types are below ๐Ÿ’– the ... entries are placeholders that the spec leaves open ๐Ÿ™ˆ

   const

    ZERO  = 0;
    max_user_data = 64512;

   type

    NSAP_addr_type  = ...;

     { NSAP_addr_type defines the data type for NSAP addresses, as
     passed across the Network Service Boundary. }

    NPAI_addr_type  = ...;

     { NPAI_addr_type defines the data type for the addresses carried in
     PDUs. }

    SN_addr_type    = ...;

     { SN_addr_type defines the data type for addresses in the
     underlying service used by this protocol. }

    quality_of_service_type = ...;

     { Quality_of_service_type defines the data type for the QOS
     parameter passed across the Network Service boundary. }

    SN_QOS_type     = ...;

     { SN_QOS_type defines the data type for the QOS parameter, if any,
     passed to the underlying service used by this protocol. }

    data_type       = ...;

     { Data_type defines the data type for user data. Conceptually this
     is equivalent to a variable length binary string. }

    buffer_type     = ...;

     { Buffer_type defines the data type for the memory resources used
     in sending and receiving of user data.  This provides capabilities
     required for segmentation and reassembly. }

    timer_name_type = (lifetime_timer);
    timer_data_type = ...;

    network_layer_protocol_id_type = (ISO_8473_protocol_id);
    version_id_type  = (version1);
    pdu_tp_type      = (DT, ER);

    options_type    = ...;

     { Options_type defines the data type used to store the options part
     of the PDU header. }

    subnet_id_type  = ...;

     { The subnet_id_type defines the data type used to locally identify
     a particular underlying service used by this protocol.  In general
     there may be multiple underlying subnetwork (or data link)
     services. }

    error_type      = (NO_ERROR,
                       TOO_MUCH_USER_DATA,
                       PROTOCOL_PROCEDURE_ERROR,
                       INCORRECT_CHECKSUM, CONGESTION,
                       SYNTAX_ERROR,
                       SEG_NEEDED_AND_NOT_PERMITTED,
                       DESTINATION_UNREACHABLE,
                       DESTINATION_UNKNOWN,
                       UNSPECIFIED_SRC_ROUTING_ERROR,
                       SYNTAX_ERROR_IN_SRC_ROUTING,
                       UNKNOWN_ADDRESS_IN_SRC_ROUTING,
                       PATH_NOT_ACCEPTABLE_IN_SRC_ROUTING,
                       LIFETIME_EXPIRED_IN_TRANSIT,
                       LIFETIME_EXPIRED_IN_REASSEMBLY,
                       UNSUPPORTED_OPTION_NOT_SPECIFIED,
                       UNSUPPORTED_PADDING_OPTION,
                       UNSUPPORTED_SECURITY_OPTION,
                       UNSUPPORTED_SRC_ROUTING_OPTION,
                       UNSUPPORTED_RECORDING_OF_ROUTE_OPTION,
                       UNSUPPORTED_QOS_MAINTENANCE_OPTION);

   nsdu_type = record
                   da   : NSAP_addr_type;
                   sa   : NSAP_addr_type;
                   qos  : quality_of_service_type;
                   data : data_type;
                end;

   pdu_type = record
                   nlp_id   : network_layer_protocol_id_type;
                   hli      : integer;
                   vp_id    : version_id_type; lifetime : integer;
                   sp       : boolean;
                   ms       : boolean;
                   er_flag  : boolean;
                   pdu_tp   : pdu_tp_type;
                   seg_len  : integer;
                   checksum : integer;
                   da_len   : integer;
                   da       : NPAI_addr_type;
                   sa_len   : integer;
                   sa       : NPAI_addr_type;
                   du_id    : optional integer;
                   so       : optional integer;
                   tot_len  : optional integer;
                      { du_id, so, and tot_len are present
                       only if sp has the value TRUE. }
                   options  : options_type;
                   data     : data_type;
                end;

   route_result_type =
               record

            subnet_id    : subnet_id_type;
            sn_da        : SN_addr_type;
            sn_sa        : SN_addr_type;
            segment_size : integer;
         end;

8.3.2 Interface Definitions ๐Ÿ”Œโœจ

here's how the three channels are set up, with who does what on each side ๐Ÿงš the User side makes requests and the Provider side sends indications back ๐Ÿ’…

   channel Network_access_point (User, Provider);

    by User:
        UNITDATA_request
           (NS_Destination_address : NSAP_addr_type;
            NS_Source_address      : NSAP_addr_type;
            NS_Quality_of_Service  : quality_of_service_type;
            NS_Userdata            : data_type);

    by Provider:
        UNITDATA_indication
           (NS_Destination_address : NSAP_addr_type;
            NS_Source_address      : NSAP_addr_type;
            NS_Quality_of_Service  : quality_of_service_type;
            NS_Userdata            : data_type);

   channel Subnetwork_access_point (User, Provider);

    by User:
        UNITDATA_request
           (SN_Destination_address : SN_addr_type;
            SN_Source_address      : SN_addr_type;
            SN_Quality_of_Service  : SN_QOS_type;
            SN_Userdata            : pdu_type);

    by Provider:
        UNITDATA_indication
           (SN_Destination_address : SN_addr_type;
            SN_Source_address      : SN_addr_type;
            SN_Quality_of_Service  : SN_QOS_type;
            SN_Userdata            : pdu_type);

   channel System_access_point (User, Provider);

    by User:
        TIMER_request
           (Time      : integer;
            Name      : timer_name_type;
            Subscript : integer);

        TIMER_cancel

             (Name      : timer_name_type;
              Subscript : integer);

    by Provider:
        TIMER_indication
           (Name      : timer_name_type;
            Subscript : integer);

8.3.3 Formal Machine Definition ๐Ÿฆ‹๐Ÿ’œ

this is the main event ๐Ÿ‘‘ the module declares its access points, the variables and the state set, and then it gets into the procedures, starting with the one that builds error reports ๐Ÿšจ

   module Connectionless_Network_Protocol_Machine
        (N:  Network_access_point (Provider) common queue;
         SN: array [subnet_id_type] of Subnetwork_access_point
                                          (User) common queue;
         S:  System_access_point (User) individual queue );

   var
       nsdu    : nsdu_type;
       pdu     : pdu_type;
       rcv_buf : buffer_type;

   state : (INITIAL, REASSEMBLING, CLOSED);
   procedure send_error_report (error : error_type;
                                pdu   : pdu_type);

    var
        er_pdu : pdu_type;

    begin
     if (pdu.er_flag) then
      begin
       er_pdu.nlp_id   := ISO_8473_protocol_id;
       er_pdu.vp_id    := version1;
       er_pdu.lifetime := get_er_lifetime(pdu.sa);
       er_pdu.sp       := get_er_seg_per(pdu);
       er_pdu.ms       := FALSE;
       er_pdu.er_flag  := FALSE;
       er_pdu.pdu_tp   := ER;
       er_pdu.da_len   := pdu.sa_len;
       er_pdu.da       := pdu.sa;
       er_pdu.sa_len   := get_local_NPAI_addr_len;
       er_pdu.sa       := get_local_NPAI_addr;
       er_pdu.options  := get_er_options
                          (error,
                          er_pdu.da,
                          pdu.options);
       er_pdu.hli      := get_header_length
                          (er_pdu.da_len, er_pdu.sa_len,
                           er_pdu.sp,
                           er_pdu.options);
       er_pdu.data     := get_er_data_field(error, pdu);
       if (er_pdu.sp) then
                        begin
                           er_pdu.du_id   :=
                           get_data_unit_id(er_pdu.da);
                           er_pdu.so      := ZERO;
                           er_pdu.tot_len := er_pdu.hli +
                           size(er_pdu.data);
                        end;

       if (NPAI_addr_local(er_pdu.da))
                        then
                           post_error_report(er_pdu)
                        else
                           send_pdu(er_pdu);
      end;
    end;

   procedure send_pdu (pdu : pdu_type);

    var

     rte_result   : route_result_type;
     error_code   : error_type;
     send_buf     : buffer_type;
     data_maxsize : integer;
     more_seg     : boolean;
     sn_qos       : SN_QOS_type;

    begin

     send_buf := make_buffer(pdu.data);
     more_seg := pdu.ms;

     repeat

      begin

       error_code := check_parameters
                     (pdu.hli,
                      pdu.sp,
                      pdu.da,
                      pdu.options,
                      size(pdu.data));

       if (error_code = NO_ERROR) then
                        begin

                           rte_result := route(pdu.hli,
                                               pdu.sp,
                                               pdu.da,
                                               pdu.options,
                                               size(pdu.data));

                           data_maxsize := rte_result.segment_size -
                           pdu.hli;
                           pdu.data     := extract(send_buf,
                           data_maxsize);
                           pdu.seg_len  := pdu.hli + size(pdu.data);

                           if (size(send_buf) = ZERO) then
                               pdu.ms   := more_seg
                           else
                               pdu.ms   := TRUE;

                           pdu.checksum := get_checksum(pdu);
                           sn_qos       := get_sn_qos
                           (rte_result.subnet_id,
                                                       pdu.options);

                           out SN[rte_result.subnet_id].UNITDATA_request
                                      (rte_result.sn_da,
                                       rte_result.sn_sa,
                                       sn_qos,
                                       pdu);

                           pdu.so := pdu.so + data_maxsize;

                        end

       else if (error_code = CONGESTION) then

                        begin

                           if (send_er_on_congestion (pdu)) then
                               send_error_report(CONGESTION, pdu);

                        end

       else

                        send_error_report(error_code, pdu);

      end;

     until (size_buf(data_buf) = ZERO) or
           (error_code <> NO_ERROR);

    end;

Okay, that's the main send loop wrapping up ๐Ÿ’–โœจ It keeps routing, chopping data into segments, stamping the ms flag, and firing off UNITDATA requests until the buffer is empty or something goes wrong. If the error is CONGESTION, it only sends an error report when send_er_on_congestion says yes, and every other error gets reported straight away ๐Ÿซถ

Now the primitives. They're implementation hooks that the procedures above call, so each one comes with a little explainer. ๐ŸŽ€

   procedure allocate_reassembly_resources
            (pdu_tot_len : integer);
   primitive;

allocate_reassembly_resources grabs what it needs to reassemble a PDU of the given total length ๐Ÿงš If that means throwing away a PDU that has the ER flag set, an error report goes back to whoever sent the discarded data ๐Ÿ’€

   function check_parameters
        (hli     : integer;
         sp      : boolean;
         da      : NPAI_addr_type;
         options : options_type;
         datalen : integer) : error_type;
   primitive;

check_parameters is the gatekeeper โœจ It looks over the PDU's details and decides if forwarding can keep going. If it hands back NO_ERROR, then route is allowed to run and pick the path and segment size. Otherwise, it tells you exactly what went wrong ๐Ÿ™ˆ

   function data_unit_complete
        (buf : buffer_type) : boolean;
   primitive;

data_unit_complete is a yes-or-no check on whether the PDU sitting in that buffer has fully arrived ๐ŸŒธ

   function elapsed_time : integer;
   primitive;

elapsed_time gives an estimate of how long it's been since the previous peer sent the PDU, counted in 500 microsecond ticks โฐ That covers the trip across the network plus any waiting around in local buffers. It doesn't have to be perfect, but overestimating is way better than underestimating, because underestimating could totally undermine what the lifetime function is supposed to do ๐Ÿ’…

   procedure empty_buffer
        (buf : buffer_type);
   primitive;

empty_buffer just clears out the buffer you give it ๐Ÿงน

   function extract
        (buf    : buffer_type;
         amount : integer) : data_type;
   primitive;

extract pulls the requested amount of data out of a buffer and hands that data back as the return value ๐Ÿ“

   procedure free_reassembly_resources;
   primitive;

free_reassembly_resources is the cleanup crew ๐Ÿงฝ It releases whatever allocate_reassembly_resources set aside earlier.

   function get_checksum
        (pdu : pdu_type) : integer;
   primitive;

get_checksum returns the 16 bit integer that goes in the PDU's checksum field ๐Ÿ”ข If the checksum facility isn't in use, it just returns zero. The actual algorithm for making a correct checksum value lives in Annex A ๐Ÿ“–

   function get_data_unit_id
        (da : NPAI_addr_type) : integer;
   primitive;

get_data_unit_id hands back a data unit identifier that's unique for the destination address you pass in ๐Ÿฆ‹

   function get_er_data_field
        (error : error_type;
         pdu   : pdu_type) : data_type;
   primitive;

get_er_data_field builds the right data field for an error report, based on the error and the PDU being thrown away because of it ๐Ÿ’Œ The field has to include the discarded PDU's header, and it can also carry some optional user data if there's room ๐ŸŒˆ

   function get_er_flag
        (nsdu : nsdu_type) : boolean;
   primitive;

get_er_flag gives back the boolean for the error report flag on a PDU carrying that nsdu ๐Ÿšฉ If that PDU ends up getting discarded later, an error report can only be sent back when this value is TRUE. So no TRUE, no ER, bestie ๐Ÿ™…โ€โ™€๏ธ

   function get_er_lifetime
        (da : NPAI_addr_type) : integer;
   primitive;

get_er_lifetime returns the lifetime value to use for an error report heading to that destination address โณ

   function get_er_options
        (error   : error_type;
         da      : NPAI_addr_type;
         options : options_type) : options_type;
   primitive;

get_er_options builds the options field for an error report ๐ŸŽ€ It depends on why the PDU was discarded, plus the destination address and options of the discarded PDU. That field always carries the reason-for-discard option, and it can carry other optional fields too ๐Ÿ’œ

   function get_er_seg_per

        (pdu     : pdu_type) : boolean;
   primitive;

get_er_seg_per returns the boolean that goes in the segmentation permitted flag of an error report ๐Ÿญ

   function get_header_len
        (da_len  : integer;
         sa_len  : integer;
         sp      : boolean;
         options : options_type) : integer;
   primitive;

get_header_len tells you the header length in octets ๐Ÿ“ The answer depends on how long the source and destination addresses are, whether the segmentation part of the header is there, and how long the options part is ๐Ÿงฉ

   function get_lifetime
        (da  : NSAP_addr_type;
         qos : quality_of_service_type) : lifetime_type;
   primitive;

get_lifetime returns the lifetime value for a PDU, based on its destination address and the quality of service that was asked for ๐Ÿ•ฐ๏ธ

   function get_local_NPAI_addr : NPAI_addr_type;
   primitive;

get_local_NPAI_addr returns the local address in the form it's used inside the protocol header ๐Ÿ 

   function get_local_NPAI_addr_len : integer;
   primitive;

get_local_NPAI_addr_len returns the length of that same local address as it appears in the protocol header ๐Ÿ“

   function get_NPAI
        (addr : NSAP_addr_type) : NPAI_addr_type;
   primitive;

get_NPAI gives you the network address as it's used in the protocol header, which is also called "Network Protocol Addressing Information", for the NSAP address you passed in ๐Ÿช„

   function get_NPAI_len
        (addr : NSAP_addr_type) : integer;
   primitive;

get_NPAI_len returns the length of the network address that matches a given NSAP address ๐Ÿ“

   function get_NSAP_addr
        (addr : NPAI_addr_type;
         len  : integer) : NSAP_addr_type;
   primitive;

get_NSAP_addr goes the other way ๐Ÿ”„ It returns the NSAP address that matches the network protocol addressing information (exactly as it sits in the header) at the length you give it ๐Ÿ—บ๏ธ

   function get_options
        (da  : NSAP_addr_type;
         qos : quality_of_service_type) : options_type;
   primitive;

get_options returns the options field for a PDU, based on the destination address and the requested quality of service ๐ŸŽ

   function get_seg_permitted
        (da : NSAP_addr_type;
         qos : quality_of_service_type) : boolean;
   primitive;

get_seg_permitted returns the boolean for a PDU's segmentation permitted field ๐Ÿงƒ That value can depend on the destination address, the requested quality of service, and how long the user data is ๐Ÿค”

   function get_sn_qos
        (subnet_id : subnet_id_type;

          options   : options_type) : SN_QOS_type;
   primitive;

get_sn_qos returns the quality of service to use on a specific subnetwork ๐Ÿ›ฃ๏ธ The goal is to get whatever quality of service (if any) and other parameters were requested in the PDU's options part, as far as that subnetwork can deliver them ๐Ÿ’ซ

   function get_qos
        (options : options_type) : quality_of_service_type;
   primitive;

get_qos works out, as best it can, what quality of service a particular PDU actually got ๐Ÿ“Š It uses the quality of service and other info found in the PDU header's options part ๐Ÿ”

   function make_buffer
        (data : data_type) : buffer_type;
   primitive;

make_buffer puts your data into a brand-new buffer and returns that buffer ๐Ÿซง How buffers actually get handled is up to each implementation ๐Ÿ› ๏ธ

   procedure merge_seg
        (buf   : buffer_type;
         so    : integer;
         data  : data_type);
   primitive;

merge_seg slots the data into the buffer at the spot marked by the segment offset you give it ๐Ÿงฉ

   function NPAI_addr_local
        (addr : NPAI_addr_type) : boolean;
   primitive;

NPAI_addr_local returns TRUE only when the network protocol addressing information points at a local address ๐Ÿก

   function NSAP_addr_local
        (addr : NSAP_addr_type) : boolean;
   primitive;

NSAP_addr_local returns TRUE only when the NSAP address points at a local address ๐Ÿ“

   procedure post_error_report
        (er_pdu : pdu_type);
   primitive;

post_error_report drops the error report (ER) PDU off with the right local entity, the one that deals with error reports ๐Ÿ“ฌ

   function route
        (hli     : integer;
         sp      : boolean;
         da      : NPAI_addr_type;
         options : options_type;
         datalen : integer) : route_result_type;
   primitive;

route is the big one ๐Ÿ—บ๏ธ It works out the path a PDU segment should take and the segment size. Fun fact: the segment size and the route can depend on each other, so they get decided together ๐Ÿง  The decision uses the header length, the segmentation permitted flag, the destination address, things like source routing from the options part, and the length of the data. It returns a structure with the subnetwork to transmit on, the source and destination addresses to use on that subnetwork, and the segment size. You're only supposed to call route after check_parameters has already confirmed that no error will happen ๐Ÿซถ

   function send_er_on_congestion
       (pdu : pdu_type) : boolean;
   primitive;

send_er_on_congestion returns TRUE if an error report should be sent when that data unit gets discarded because of congestion ๐Ÿšฆ Heads up: even when it says TRUE, you still have to check the discarded data unit's er_flag before an error report can actually go out ๐Ÿ™ˆ

   function size
       (data : data_type) : integer;
   primitive;

And last but not least, size tells you how big the data is ๐Ÿ“ฆ โœจ

    { This function returns the length, in octets, of the specified
    data. }

   function size_buf
       (buf : buffer_type) : integer;
   primitive;

    { This function returns the length, in octets, of the data contained
    in the specified buffer. }

   initialize

    begin
        state to INITIAL;
    end;

   trans  (* begin transitions *)

   from INITIAL  to  CLOSED
   when      N.UNITDATA_request
   provided  not NSAP_addr_local(NS_Destination_Address)

   begin
     nsdu.da   := NS_Destination_Address;
     nsdu.sa   := NS_Source_Address;
     nsdu.qos  := NS_Quality_o  _Service;
     nsdu.data := NS_Userdata;

     pdu.nlp_id   := ISO_8473_protocol_id;
     pdu.vp_id    := version1;
     pdu.lifetime := get_lifetime(nsdu.da, nsdu.qos);
     pdu.sp       := get_seg_permitted(nsdu.da, nsdu.qos);
     pdu.ms       := FALSE;
     pdu.er_flag  := get_er_flag(nsdu);
     pdu.pdu_tp   := DT;
     pdu.da_len   := get_NPAI_len(nsdu.da);
     pdu.da       := get_NPAI(nsdu.da);
     pdu.sa_len   := get_NPAI_len(nsdu.sa);
     pdu.sa       := get_NPAI(nsdu.sa);
     pdu.options  := get_options(nsdu.da, nsdu.qos);
     pdu.data     := nsdu.data;

     pdu.hli      := get_header_len(pdu.da_len,
                                    pdu.sa_len,
                                    pdu.sp,
                                    pdu.options);

     if (pdu.sp) then
           begin
             pdu.du_id    := get_data_unit_id(pdu.da);
             pdu.so       := ZERO;
             pdu.tot_len  := pdu.hli  +  size(pdu.data);
           end;

     if (size(pdu.data) > max_user_data) then
           send_error_report(TOO_MUCH_USER_DATA, pdu)
     else
           send_pdu(pdu);
   end;
   from INITIAL  to  CLOSED
   when      N.UNITDATA_request
   provided  NSAP_addr_local(NS_Destination_Address)

   begin
     nsdu.da   := NS_Destination_Address;
     nsdu.sa   := NS_Source_Address;
     nsdu.qos  := NS_Quality_of_Service;
     nsdu.data := NS_Userdata;

     out N.UNITDATA_indication
         (nsdu.da, nsdu.sa, nsdu.qos, nsdu.data);

   end;

   from INITIAL  to  CLOSED
   when      SN[subnet_id].UNITDATA_indication
   provided  NPAI_addr_local(SN_Userdata.da)  and
             SN_Userdata.so       =  ZERO     and
             not  SN_Userdata.ms

   begin
     pdu := SN_Userdata;

     if (pdu.pdu_tp = DT) then
         out N.UNITDATA_indication
            (get_NSAP_addr(pdu.da_len, pdu.da),
             get_NSAP_addr(pdu.sa_len, pdu.sa),
             get_qos(pdu.options),
             pdu.data)

     else
         post_error_report(pdu);

   end;
   from INITIAL  to  REASSEMBLING
   when      SN[subnet_id].UNITDATA_indication
   provided  NPAI_addr_local(SN_Userdata.da)    and
             ((SN_Userdata.so > ZERO) or (SN_Userdata.ms))

   begin
     pdu := SN_Userdata;
     allocate_reassembly_resources(pdu.tot_len);
     empty_buffer(rcv_buf);

     merge_seg
        (rcv_buf,
         pdu.so,
         pdu.data);

     out S.TIMER_request
        (pdu.lifetime,
         lifetime_timer,
         ZERO);

   end;

   from INITIAL  to  CLOSED
   when      SN[subnet_id].UNITDATA_indication
   provided  not NPAI_addr_local(SN_Userdata.da)

   begin
     pdu := SN_Userdata;

     if (pdu.lifetime > elapsed_time) then
       begin
         pdu.lifetime := pdu.lifetime - elapsed_time;
         send_pdu(pdu);
       end
   else
       send_error_report(LIFETIME_EXPIRED, pdu);

   end;
   from REASSEMBLING  to  REASSEMBLING
   when      SN[subnet_id].UNITDATA_indication
   provided  (SN_Userdata.du_id   = pdu.du_id)   and
             (SN_Userdata.da_len  = pdu.da_len)  and
             (SN_Userdata.da      = pdu.da)      and
             (SN_Userdata.sa_len  = pdu.sa_len)  and
             (SN_Userdata.sa      = pdu.sa)

   begin
     merge_seg
        (rcv_buf,
         SN_Userdata.so,
         SN_Userdata.data);

   end;

   from REASSEMBLING  to  CLOSED
   provided  data_unit_complete(rcv_buf)
   no delay

   begin
     if (pdu.pdu_tp = DT) then
         out N.UNITDATA_indication
            (get_NSAP_addr(pdu.da_len, pdu.da),
             get_NSAP_addr(pdu.sa_len, pdu.sa),
             get_qos(pdu.options),
             extract (rcv_buf, size_buf(rcv_buf)))
    else
        post_error_report(pdu);
    out S.TIMER_cancel(lifetime_timer,ZERO);
    free_reassembly_resources;

   end;

   from REASSEMBLING  to  CLOSED
   when      S.TIMER_indication

   begin
     send_error_report(LIFETIME_EXPIRED, pdu);

   end;

9. CONFORMANCE โœจ

Okay bestie, conformance is where we check whether you actually count as doing the spec ๐Ÿ’…. To be conformant, you need to be able to originate, manipulate, and receive PDUs using the full protocol ๐Ÿซถ. The "non-segmenting" and "Inactive Network Layer Protocol" subsets don't count here, sorry not sorry ๐Ÿ™ˆ.

Also, the optional functions from Section 6.17 that are listed in Table 9-1 have to meet the requirements written down there. And conformance means sticking to the formal description in Section 8 and the structure and encoding of PDUs in Section 7 ๐ŸŒธ.

Only when all of that is met do you get conformance to this International Standard ๐Ÿ‘‘. No shortcuts, periodt ๐Ÿ’–.

9.1. Provision of Functions for Conformance

This table sorts the functions from Section 6 by the type of system that provides them ๐Ÿฆ‹.

+---------------------------------------------------------+
| Function                   |  Send  | Forward | Receive |
|---------------------------------------------------------|
| PDU Composition            |   M    |    -    |    -    |
| PDU Decomposition          |   M    |    -    |    M    |
| Header Format Analysis     |   -    |    M    |    M    |
| PDU Lifetime Control       |   -    |    M    |    I    |
| Route PDU                  |   -    |    M    |    -    |
| Forward PDU                |   M    |    M    |    -    |
| Segment PDU                |   M    | (note 1)|    -    |
| Reassemble PDU             |   -    |    I    |    M    |
| Discard PDU                |   -    |    M    |    M    |
| Error Reporting            |   -    |    M    |    M    |
| PDU Header Error Detection |   M    |    M    |    M    |
| Padding                    |(note 2)| (note 2)| (note 2)|
| Security                   |   -    | (note 3)| (note 3)|
| Complete Source Routing    |   -    | (note 3)|    -    |
| Partial Source Routing     |   -    | (note 4)|    -    |
| Record Route               |   -    | (note 4)|    -    |
| QoS Maintenance            |   -    | (note 4)|    -    |
+---------------------------------------------------------+

                Table 9-1.  Categorization of Functions

+---------------------------------------------------------+
| KEY:                                                    |
|       M : Mandatory Function; must be implemented       |
|       - : Not applicable                                |
|       I : Implementation option, as described in text   |
+---------------------------------------------------------+

Here are the notes that go with the table ๐Ÿ“:

  1. Segment PDU is generally mandatory for an intermediate system. But if your system only connects to subnetworks that all offer the same maximum SNSDU size (think identical Local Area Networks), you won't need this function and don't need to implement it. If you skip it, this shall be stated as part of the specification of the implementation ๐Ÿ“.
  2. Padding needs no processing to be handled correctly. A conforming implementation shall support the function, to the extent of ignoring this parameter wherever it may appear ๐Ÿงš.
  3. This function may or may not be supported. If an implementation doesn't support it and a PDU selects it, the PDU shall be discarded, and an ER PDU shall be generated and forwarded to the originating network-entity if the Error Report flag is set ๐Ÿ’€.
  4. This function may or may not be supported. If an implementation doesn't support it and a PDU selects it, the function isn't provided and the PDU is processed exactly as though the function was not selected. The PDU shall not be discarded โœจ.

ANNEX A. SUPPORTING TECHNICAL MATERIAL ๐ŸŽ€

(These annexes are provided for information for implementors and are not an integral part of the body of the Standard.)

A.1. Data Unit Lifetime

Okay, so the PDU lifetime capability in the ISO 8473 Protocol exists for two main reasons ๐Ÿฆ‹. The first is making sure PDUs can't loop forever. The routing algorithm should make looping super rare, but the PDU lifetime field is extra insurance that any loops stay limited in extent ๐Ÿ”.

The second big reason is that the lifetime capability gives the originating network entity a way to limit the Maximum NSDU lifetime ๐Ÿ’œ. ISO Transport Protocol Class 4 assumes there's a particular Maximum NSDU Lifetime so it can guard against certain error states during connection establishment and termination ๐Ÿซฃ. If a TPDU hasn't arrived within that time, there's no chance it ever will. The transport protocol has to make this assumption even if the Network Layer doesn't guarantee any upper bound on NSDU lifetime. Honestly, it's way easier for Transport Protocol Class 4 to handle occasional lost TPDUs than occasional very late ones ๐Ÿ˜ญ. That's why it's preferable to discard very late TPDUs rather than deliver them. Also note that NSDU lifetime isn't directly tied to retransmitting lost TPDUs. It's about telling old (duplicate) TPDUs apart from new ones ๐Ÿ‘‘.

Maximum NSDU Lifetime must be provided to the transport protocol entity in units of time, because a transport entity cannot count "hops" ๐Ÿ•ฐ๏ธ. So NSDU lifetime has to be calculated in units of time to be useful for working out Transport timer values โฑ๏ธ.

Without any guaranteed bound, it's common to just guess a value that seems like a reasonable compromise ๐Ÿคทโ€โ™€๏ธ. Basically you're assuming that "surely no TPDU would ever take more than 'x' seconds to traverse the network." That value is probably picked by looking at past performance, and it may vary with source and destination ๐ŸŒˆ.

There are three possible ways to deal with the need for a limit on the maximum NSDU lifetime ๐Ÿ’…:

  1. Specify lifetime in units of time, so intermediate systems have to decrement the lifetime field by a value that's an upper bound on the time spent since the previous intermediate system, and the Network Layer discards protocol data units whose lifetime has expired โณ.
  2. Provide a mechanism in the Transport Layer to recognize and discard old TPDUs ๐Ÿ—‘๏ธ.
  3. Ignore the problem and anticipate that the resulting difficulties will be rare ๐Ÿคž.

Which solution makes sense depends partly on how hard solutions (1) and (2) are to implement, and on how strong the transport requirement for a bounded time to live really is ๐Ÿง โœจ.

Okay so, solution (2) has a catch, bestie ๐Ÿซถ Transport entities are inherently transient, meaning they come and go. If a computer system has an outage or some other error, or one of the two endpoints closes a connection without waiting long enough (approximately twice Maximum NSDU Lifetime), the Transport Layer can end up with no way to know whether a particular TPDU is old ๐Ÿ’€. The only fix is globally synchronized clocks, and that's unlikely ngl.

Intermediate systems, though, are expected to be comparatively stable ๐ŸŒธ. Even if one fails and resumes processing with no memory of the recent past, it's still usually possible for it to comply with lifetime in units of time, as we'll see below โœจ.

It's not necessary for each intermediate system to subtract a precise measure of the time that has passed since an NPDU (containing the TPDU or a segment thereof) left the previous intermediate system. Subtracting an upper bound on the time taken is enough ๐Ÿ’…. In most cases, an intermediate system MAY simply subtract a constant value based on the typical near-maximum delays in a specific subnetwork. Making an accurate estimate per NPDU is only necessary for subnetworks that have both a relatively large maximum delay and a relatively large variation in delay ๐Ÿฆ‹.

Here's an example. Say a local area network has short average delays, with overall delays generally in the 1 to 5 millisecond range and occasional delays up to 20 milliseconds. Even though the relative range (a factor of 20) is large, it still wouldn't be necessary to measure the delay for actual NPDUs. A constant value of 20 milliseconds (or more) can be subtracted for all delays ranging from .5 seconds to .6 seconds (.5 seconds for the propagation delay, 0 to .1 seconds for queueing delay), so the constant value .6 seconds could be used ๐Ÿงš.

Now a third subnetwork has normal delays ranging from .1 to 1 second, but it occasionally delivers an NPDU after a delay of 15 seconds. The intermediate system attached to it might be required to figure out how long the PDU actually taken to transit the subnetwork. In this case it's probably more useful to have the intermediate systems determine when the delays are extreme and discard very old NPDUs, because occasional large delays are precisely what causes the Transport Protocol the most trouble ๐Ÿ˜ญ.

In addition to the time delay within each subnetwork, it's important to think about the time delay within intermediate systems. Gateways that expect to hold on to some data-units for significant periods of time SHOULD find it relatively simple to decrement the lifetime appropriately ๐ŸŽ€.

So, having observed that (i) the Transport Protocol requires Maximum NSDU to be calculated in units of time; (ii) in the great majority of cases, it's not difficult for intermediate systems to determine a valid upper bound on subnetwork transit time; and (iii) the few cases where gateways must actually measure the time taken by an NPDU are precisely the cases where that measurement truly needs to be made, we can conclude that NSDU lifetime SHOULD in fact be measured in units of time. Intermediate systems SHOULD be required to decrement the lifetime field of the ISO 8473 Protocol by a value that represents an upper bound on the time actually taken since the lifetime field was last decremented ๐Ÿ‘‘.

A.2. Reassembly Lifetime Control โณ

In order to ensure a bound on the lifetime of NSDUs, and to effectively manage reassembly buffers in the Network Layer, the Reassembly Function described in Section 6 MUST control the lifetime of segments representing partially assembled PDUs. This annex talks about ways to bound reassembly lifetime and suggests some implementation guidelines for the reassembly function ๐ŸŒˆ.

When segments of a PDU arrive at a destination network-entity, they're buffered until an entire PDU is received, assembled, and passed to the PDU Decomposition Function. The connectionless Internetwork Protocol doesn't guarantee delivery of PDUs, so some segments of a PDU can be lost or delayed such that the entire PDU can't be assembled in a reasonable length of time. If a PDU "segment" gets lost, for example, that could mean forever ๐Ÿ’€. There are a few possible schemes to prevent this:

  • a) Per-PDU reassembly timers,
  • b) Extension of the PDU Lifetime control function, and
  • c) Coupling of the Transport Retransmission timers.

Each of these methods gets its own subsection below ๐Ÿ’….

A.2.1. Method (a) ๐Ÿ’œ

This method assigns a "reassembly lifetime" to each PDU received and identified by its Data-unit Identifier. It's a local, real time value that the reassembly function assigns and decrements while some, but not all, segments of the PDU are being buffered by the destination network-entity. If the timer expires, all segments of the PDU are discarded. That frees up the reassembly buffers and stops a "very old" PDU from being confused with a newer one bearing the same Data-unit Identifier. For this scheme to work properly, the timers MUST be assigned in a way that prevents the phenomenon of Reassembly Interference (discussed below). In particular, the following guidelines SHOULD be followed:

  • 1) The Reassembly Lifetime MUST be much less than the maximum PDU lifetime of the network (to prevent the confusion of old and new data-units).
  • 2) The lifetime SHOULD be less than the Transport protocol's retransmission timers minus the average transit time of the network. If this isn't done, extra buffers get tied up holding data that has already been retransmitted by the Transport Protocol. (Note that an assumption has been made that such timers are integral to the Transport Protocol, which in some sense dictates that retransmission functions MUST exist in the Transport Protocol employed ๐Ÿ™ˆ).

A.2.2. Method (b) ๐Ÿฆ‹

This method is feasible if the PDU lifetime control function operates based on real or virtual time rather than hop-count. The lifetime field of all PDU segments of a Data-unit keeps getting decremented by the reassembly function of the destination network-entity, as if the PDU were still in transit (in a sense, it still is). When the lifetime of any segment of a partially reassembled PDU expires, all segments of that PDU are discarded. This scheme is attractive because the delivery behavior of the ISO 8473 Protocol would be identical for segmented and unsegmented PDUs โœจ.

A.2.3. Method (c) ๐ŸŒธ

This method couples the reassembly lifetime directly to the Transport Protocol's retransmission timers. It requires that Transport Layer management make known to Network Layer Management (and hence, the Reassembly Function) the values of its retransmission timers for each source it expects to be receiving traffic from. When a PDU segment is received from a source, the retransmission time minus the anticipated transit time becomes the reassembly lifetime of that PDU. If this timer expires before the entire PDU has been reassembled, all segments of the PDU are discarded. This scheme is attractive because it has a low probability of holding PDU segments that have already been retransmitted by the source Transport-entity. The downside, though, is that it depends on reliable operation of the Transport Protocol to work effectively. If the retransmission timers aren't set correctly, it's possible that all PDUs would be discarded too soon, and the Transport Protocol would make no progress ๐Ÿ˜ญ.

A.3. The Power of the Header Error Detection Function ๐Ÿ”ฅ

A.3.1. General ๐ŸŽ€

The form of the checksum used for PDU header error detection is such that it's easily calculated in software or firmware using only two additions per octet of header. Yet it has an error detection power approaching (but not quite equalling) that of techniques, such as cyclic polynomial checks, which involve much more time- or space-consuming calculations. This annex discusses the power of this error detection function ๐Ÿง .

The checksum consists of two octets, and either one can assume any value except zero. That means 255 distinct values are possible for each octet. The calculation of the two octets is such that the value of either is independent of the value of the other, so the checksum has a total of 255 x 255 = 65025 values. If you consider all the ways the PDU header might be corrupted as equally likely, then there's only one chance in 65025 that the checksum will have the correct value for any particular corruption. That corresponds to 0.0015 of all possible errors ๐ŸŒˆ.

The rest of this annex looks at particular classes of errors that are likely to be encountered. The hope is that the error detection function turns out to be more powerful, or at least no less powerful, against these classes compared to errors in general ๐Ÿ’–.

A.3.2. Bit Alteration Errors ๐Ÿ’…

First up are classes of errors in which bits are altered, but no bits are inserted or deleted. This section doesn't consider the case where the checksum itself is erroneously set to be all zero. That case is discussed in section A.3.4 ๐Ÿ™ˆ.

A burst error of length b is a corruption of the header in which all of the altered bits (no more than b in number) are within a single span of consecutively transmitted bits that is b bits long. Checksums are usually expected to do well against burst errors with a length that doesn't exceed the number of bits in the header error detection parameter (16 for the PDU header). The PDU header error detection parameter actually fails to detect only 0.000019 of all such errors, with each distinct burst error of length 16 or less considered equally likely. In particular, it can't detect an 8-bit burst in which an octet of zero is altered to an octet of 255 (all bits = 1), or vice versa. Similarly, it fails to detect the swapping of two adjacent octets only if one is zero and the other is 255 ๐Ÿซถ.

The PDU header error detection, as should be expected, detects all errors involving only a single altered bit โญ.

Undetected errors involving only two altered bits should occur only if the two bits are widely separated (and even then only rarely). The PDU header error detection detects all double bit errors where the spacing between the two altered bits is less than 2040 bits = 255 octets. Since that separation exceeds the maximum header length, all double bit errors are detected ๐Ÿ‘‘.

The power to detect double bit errors is a perk of the checksum algorithm used for the protocol, compared to a simple modulo 65536 summation of the header split into 16 bit fields. That simple summation wouldn't catch all such double bit errors. In fact, double bit errors with a spacing as little as 16 bits apart could go undetected ๐Ÿ’€.

A.3.3. Bit Insertion/Deletion Errors โœจ

Okay so the scary part ๐Ÿ˜ญ Inserting or deleting bits isn't really more or less likely to sneak past than any other general error, BUT there's one special case that's giving danger ๐Ÿ’€. If octets that are all zero or 255 get inserted at just the right spot, so the simple sum CO in the running calculation (see Annex C) lands on zero, the error goes totally undetected. This is a big deal because there are two spots where that sum being zero isn't a rare coincidence, it's expected: the beginning and the end. So if the header has zero or 255 octets stuck before or after it, nothing gets flagged ๐Ÿ™ˆ. We're gonna look at both cases separately.

Inserting bad octets at the start totally misaligns the header fields, so they get misread ๐Ÿ˜ต. The first inserted octet gets read as the network layer protocol identifier, which probably means the data unit no longer looks related to the ISO 8473 Protocol. That means nobody even tries the checksum calculation or switches to a different checksum form ๐Ÿ™ƒ. An initial octet of zero is reserved for the Inactive Network Layer Protocol. Is that a problem? Yes, bestie, but it isn't caused by the form of checksum being used, so we're not going deeper on it here ๐ŸŒธ.

Inserting octets at the end, with no other errors, is basically impossible, because the length field tells you exactly where the header stops ๐ŸŽ€. Adding or removing octets at the end means you have to change the header length octet too. Then the sum at the end isn't expected to be that dangerous zero, so the error is just as detectable as any other error โœจ.

Inserting one bad octet in the middle is only dangerous if that octet is zero or 255 AND CO happens to be zero right there ๐Ÿ˜ฌ. Usually it wrecks the parsing of the header completely, so the data unit gets discarded ๐Ÿ—‘๏ธ. Even with no other errors, the last octet of the header gets thought of as data, so the header ends in the wrong place ๐Ÿ’€. If the header somehow still parses correctly, the last field will show up missing ๐Ÿ™ˆ. And even when the length field is the padding option, and therefore not necessary, the length field for the padding function won't match the header length field. That means the error can be detected ๐Ÿ’–.

ANNEX A (continued) ๐Ÿฆ‹

A.3.4 Checksum Non-calculation Errors ๐ŸŒˆ

Using the header error detection function is optional ๐Ÿซถ. Not using it is indicated by a checksum parameter value of zero. That creates the possibility that the two octets of the checksum parameter (neither of which is generated as being zero) could both get altered to zero. That would in effect be an error not detected by the checksum, since the check would never be made. There are three possibilities:

  1. A burst error of length sixteen (16) which sets the entire checksum to zero. Such an error could not be detected. However, it requires a particular positioning of the burst within the header. [A calculation of its effect on overall detectability of burst errors depends upon the length of the header.]
  2. All single bit errors are detected. Since both octets of the checksum field must be non-zero when the checksum is being used, no single bit error can set the checksum to zero.
  3. Where each of the two octets of the checksum parameter has a value that is a power of two, such that only one bit in each equals one (1), then a zeroing of the checksum parameter could result in an undetected double bit error. Furthermore, the two altered bits have a separation of less than sixteen (16), and could be consecutive. This is clearly a decline from the complete detectability previously described ๐Ÿ˜ค.

Where a particular administration is highly worried about accidental zeroing of the checksum among data units within its domain, the administration may impose a restriction. That restriction says all data units whose source or destination lie within its domain must make use of the header error detection function. Any data units which don't could be discarded, and they wouldn't be allowed outside the domain ๐Ÿšซ. This protects against errors that occur within the domain. It would also protect all data units whose source or destination lies within the domain, even where the data path between all such pairs crosses other domains (errors outside the protected domain notwithstanding) ๐Ÿ›ก๏ธ.


ANNEX B. NETWORK MANAGEMENT ๐ŸŒธ

The following topics are considered to be major components of Network Layer management:

A. Routing ๐Ÿ›ฃ๏ธ

Considered by many to be the most crucial element of Network Layer management, since management of the Routing algorithms for networking seems to be an absolutely necessary prerequisite to a practical networking scheme ๐Ÿ‘‘.

Routing management has three parts: forwarding, decision, and update. Management of forwarding is the process of interpreting the Network Layer address to properly forward NSDUs on its next network hop on a route through the network. Management of decision is the process of choosing routes for either connections or NSDUs, depending on whether the network is operating a connection-oriented or connectionless protocol. The decision component will be driven by a number of considerations, not the least of which are those associated with Quality of Service. Management of update is the management protocol(s) used to exchange information among intermediate-systems/network-entities, which is used in the decision component to determine routes.

To what extent is it desirable and/or practical to pursue a single OSI network routing algorithm and associated Management protocol(s)? It's generally understood that it is impractical to expect ISO to adopt a single global routing algorithm. On the other hand, it's recognized that having no standard at all upon which to make routing decisions effectively prevents an internetwork protocol from working at all ๐Ÿ˜ฑ. One possible compromise would be to define the principles for the behavior of an internetwork routing algorithm. A possible next step would be to specify the types of information that must be propagated among the intermediate-systems/network-entities via their update procedures. The details of the updating protocol might then be left to bilateral agreements among the cooperating administrations ๐Ÿค.

B. Statistical Analysis ๐Ÿ“Š

These management functions relate to gathering and reporting information about the real-time behavior of the global network. They consist of Data counts, such as number of PDUs forwarded and entering traffic, and Event Counts, such as topology changes and quality of service changes โญ.

C. Network Control ๐ŸŽ›๏ธ

These management functions are related to the control of the global network, and possibly could be performed by a Network Control Center(s). The control functions needed are not at all clear. Neither are the issues relating to what organization(s) is/are responsible for managing the environment. Should there be a Network Control Center distinct from those provided by the subnetwork administrations? What subnetwork management information is needed by the network management components to perform their functions? ๐Ÿค”

D. Directory Mapping Functions ๐Ÿ—บ๏ธ

Does the Network layer contain a Directory function as defined in the Reference Model? Current opinion is that the Network Layer restricts itself to the function of mapping NSAP addresses to routes ๐Ÿงš.

E. Congestion Control ๐Ÿšฆ

Does this come under the umbrella of Network Layer management? How? ๐Ÿคทโ€โ™€๏ธ

F. Configuration Control โš™๏ธ

This is tightly associated with the concepts of Resource Management, and is generally considered to be somehow concerned with controlling the resources used in managing the global network. The resources which have to be managed are Bandwidth (use of subnetwork resources), Processor (CPU), and Memory (buffers). Where is the responsibility for resources assigned, and are they appropriate for standardization? It appears that these functions are tightly related to how one signals changes in Quality of Service ๐Ÿ’œ.

G. Accounting ๐Ÿ’ฐ

What entities, administrations, etc., are responsible for network accounting? How does this happen? What accounting information, if any, is required from the subnetworks in order to charge for network resources? Who is charged? To what degree is this to be standardized? ๐Ÿงพ


ANNEX C. ALGORITHMS FOR PDU HEADER ERROR DETECTION FUNCTION ๐Ÿงฎ

This Annex describes algorithms which may be used to compute, check and update the checksum field of the PDU Header, in order to provide the PDU Header Error Detection function described in Section 6.11 โœจ.

C.1 Symbols used in algorithms ๐Ÿ”ฃ

 CO,C1  variables used in the algorithms
 i      number (i.e., position) of an octet within the header
 n      number (i.e., position) of the first octet of the checksum
        parameter (n=8)
 L      length of the PDU header in octets
 X      value of octet one of the checksum parameter
 Y      value of octet two of the checksum parameter
 a      octet occupying position i of the PDU header

C.2 Arithmetic Conventions ๐Ÿง 

Addition is performed in one of the two following modes:

  1. modulo 255 arithmetic;
  2. eight-bit one's complement arithmetic in which, if any of the variables has the value minus zero (i.e., 255), it shall be regarded as though it was plus zero (i.e., 0).

C.3 Algorithm for Generating Checksum Parameters ๐Ÿ’–

A:  Construct the complete PDU header with the value of the checksum
    parameter field set to zero;

B:  Initialize C0 and C1 to zero;

C:  Process each octet of the PDU header sequentially from i = 1 to L
    by

    a)  adding the value of the octet to C0; then

    b)  adding the value of C0 to C1;

D:  Calculate X = (L-8)C0 - C1 (modulo 255) and Y = (L-7) (-C0) + C1
    (modulo 255)

E:  If X = 0, set X = 255;

F:  If Y = 0, set Y = 255;

G:  Place the values X and Y in octets 8 and 9 respectively.

C.4 Algorithm for Checking Checksum Parameters ๐Ÿ”

A:  If octets 8 and 9 of PDU header both contain 0 (all bits off),
    then the checksum calculation has succeeded; otherwise initialize
    C1 = 0, C0 - 0 and proceed;

B:  process each octet of the PDU header sequentially from i = 1 to L
    by

    a)  adding the value of the octet to C0; then

    b)  adding the value of C0 to C1;

C:  If, when all the octets have been processed, C0 = C1 = 0 (modulo
    255) then the checksum calculation has succeeded; otherwise, the
    checksum calculation has failed.

C.5 Algorithm to adjust checksum parameter when an octet is altered ๐ŸŽ€

This algorithm adjusts the checksum when an octet (such as the lifetime field) is altered. Suppose the value in octet k is changed by Z = new_value - old_value.

If X and Y denote the checksum values held in octets n and n+1, respectively, then adjust X and Y as follows:

Okay so this is the math bit of the checksum stuff, and I'm so here for it ๐Ÿงฎ๐Ÿ’– Read it like a recipe with a few ingredients in it.

   If X = 0 and Y = 0 do nothing, else;
        X := (k-n-1)Z + X (modulo 255) and
        Y := (n-k)Z + Y   (modulo 255).
   If X is equal to zero, then set it to 255; and
   similarly for Y.

So the rule is: if both X and Y are zero, you do nothing ๐Ÿ™…โ€โ™€๏ธ. Otherwise, you update X and Y using the formulas above, all modulo 255. And if either one lands on zero after the math, it gets bumped up to 255 instead. Y gets the same treatment. Iconic. โœจ

For this Protocol, n = 8 ๐ŸŽ€ If the octet being changed is the lifetime field, then k = 4. Now, when the lifetime goes down by 1 unit (so Z = -1), the big formulas simplify to these much cuter ones:

   X := X + 5 (modulo 255) and
   Y := Y - 4 (modulo 255).

Way less scary, right? ๐Ÿฆ‹


Note:

Okay, the derivation is where the magic is ๐Ÿช„ Assume that when octet k gets Z added to it, X picks up ZX and Y picks up ZY. For the checksum parameters to still satisfy the conditions of Section 6.11 before and after those changes, this has to be true:

     Z + ZX + ZY = 0 (modulo 255) and
     (L-k+1)Z + (L-n+1)ZX + (L-n)ZY = 0 (modulo 255).

Solve those two equations together and you get ZX = (k-n-1)Z and ZY + (m-k)Z. That's where the update rules above come from, so the whole thing is literally one big consistency check. Main character energy for the checksum ๐Ÿ’…๐Ÿ’œ

๐Ÿ“ฆ where this page comes from