RFC 5533

Shim6: Level 3 Multihoming Shim Protocol for IPv6

๐Ÿ“… published June 2009, from ietf

RFC 5533: Shim6: Level 3 Multihoming Shim Protocol for IPv6 ๐ŸŽ€

okay so bestie, this is RFC 5533, and it's giving Standards Track ๐Ÿ‘‘. It was written by Erik Nordmark of Sun Microsystems and Marcelo Bagnulo of UC3M, and it's dated June 2009 ๐Ÿ“…. The header doesn't list anything it obsoletes or updates, so it's not replacing or patching any earlier RFC ๐ŸŒธ. Its whole job is defining the Shim6 protocol ๐Ÿฆ‹.

Status of This Memo โœจ

okay, so this is an Internet standards track protocol for the Internet community, and the authors are asking for discussion and suggestions for improvements ๐Ÿ’–. If you want the official standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š. Distribution of this memo is unlimited ๐ŸŒˆ.

Copyright (c) 2009 IETF Trust and the persons identified as the document authors. All rights reserved ๐Ÿ”’. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents in effect on the date it was published, which you can find at http://trustee.ietf.org/license-info ๐Ÿ“œ. Please read those carefully, bestie, because they spell out your rights and restrictions for this document ๐Ÿซถ.

Abstract ๐Ÿงš

So the main idea here is Shim6, which is a layer 3 shim ๐Ÿ’œ. Its big trick is locator agility underneath the transport protocols, which means multihoming for IPv6 gets failover and load-sharing properties ๐Ÿ”ฅ. The best part is that it doesn't assume a multihomed site has a provider-independent IPv6 address prefix announced in the global IPv6 routing table, so it's way less dependent on that ๐Ÿ™ˆ.

Here's the flow: the hosts in a site with multiple provider-allocated IPv6 address prefixes use Shim6 to set up state with their peer hosts โœจ. Later, if the original locator pair stops working, that saved state lets them failover to a different locator pair ๐Ÿฆ‹. It's giving resilience, no cap ๐Ÿ’€.

Table of Contents ๐Ÿ“

   1. Introduction ....................................................4
      1.1. Goals ......................................................5
      1.2. Non-Goals ..................................................5
      1.3. Locators as Upper-Layer Identifiers (ULID) .................6
      1.4. IP Multicast ...............................................7
      1.5. Renumbering Implications ...................................8
      1.6. Placement of the Shim ......................................9
      1.7. Traffic Engineering .......................................11
   2. Terminology ....................................................12
      2.1. Definitions ...............................................12
      2.2. Notational Conventions ....................................15
      2.3. Conceptual ................................................15
   3. Assumptions ....................................................15
   4. Protocol Overview ..............................................17
      4.1. Context Tags ..............................................19
      4.2. Context Forking ...........................................19
      4.3. API Extensions ............................................20
      4.4. Securing Shim6 ............................................20
      4.5. Overview of Shim Control Messages .........................21
      4.6. Extension Header Order ....................................22
   5. Message Formats ................................................23
      5.1. Common Shim6 Message Format ...............................23
      5.2. Shim6 Payload Extension Header Format .....................24
      5.3. Common Shim6 Control Header ...............................25
      5.4. I1 Message Format .........................................26
      5.5. R1 Message Format .........................................28
      5.6. I2 Message Format .........................................29
      5.7. R2 Message Format .........................................31
      5.8. R1bis Message Format ......................................33
      5.9. I2bis Message Format ......................................34
      5.10. Update Request Message Format ............................37
      5.11. Update Acknowledgement Message Format ....................38
      5.12. Keepalive Message Format .................................40
      5.13. Probe Message Format .....................................40
      5.14. Error Message Format .....................................40
      5.15. Option Formats ...........................................42
           5.15.1. Responder Validator Option Format .................44
           5.15.2. Locator List Option Format ........................44
           5.15.3. Locator Preferences Option Format .................46
           5.15.4. CGA Parameter Data Structure Option Format ........48
           5.15.5. CGA Signature Option Format .......................49
           5.15.6. ULID Pair Option Format ...........................49
           5.15.7. Forked Instance Identifier Option Format ..........50
           5.15.8. Keepalive Timeout Option Format ...................50
   6. Conceptual Model of a Host .....................................51
      6.1. Conceptual Data Structures ................................51
      6.2. Context STATES ............................................52
   7. Establishing ULID-Pair Contexts ................................54
      7.1. Uniqueness of Context Tags ................................54
      7.2. Locator Verification ......................................55
      7.3. Normal Context Establishment ..............................56
      7.4. Concurrent Context Establishment ..........................56
      7.5. Context Recovery ..........................................58
      7.6. Context Confusion .........................................60
      7.7. Sending I1 Messages .......................................61
      7.8. Retransmitting I1 Messages ................................62
      7.9. Receiving I1 Messages .....................................62
      7.10. Sending R1 Messages ......................................63
           7.10.1. Generating the R1 Validator .......................64
      7.11. Receiving R1 Messages and Sending I2 Messages ............64
      7.12. Retransmitting I2 Messages ...............................65
      7.13. Receiving I2 Messages ....................................66
      7.14. Sending R2 Messages ......................................67
      7.15. Match for Context Confusion ..............................68
      7.16. Receiving R2 Messages ....................................69
      7.17. Sending R1bis Messages ...................................69
           7.17.1. Generating the R1bis Validator ....................70
      7.18. Receiving R1bis Messages and Sending I2bis Messages ......71
      7.19. Retransmitting I2bis Messages ............................72
      7.20. Receiving I2bis Messages and Sending R2 Messages .........72
   8. Handling ICMP Error Messages ...................................74
   9. Teardown of the ULID-Pair Context ..............................76
   10. Updating the Peer .............................................77
      10.1. Sending Update Request Messages ..........................77
      10.2. Retransmitting Update Request Messages ...................78
      10.3. Newer Information while Retransmitting ...................78
      10.4. Receiving Update Request Messages ........................79
      10.5. Receiving Update Acknowledgement Messages ................81
   11. Sending ULP Payloads ..........................................81
      11.1. Sending ULP Payload after a Switch .......................82
   12. Receiving Packets .............................................83
      12.1. Receiving Payload without Extension Headers ..............83
      12.2. Receiving Shim6 Payload Extension Headers ................83
      12.3. Receiving Shim Control Messages ..........................84
      12.4. Context Lookup ...........................................84
   13. Initial Contact ...............................................86
   14. Protocol Constants ............................................87
   15. Implications Elsewhere ........................................88
      15.1. Congestion Control Considerations ........................88
      15.2. Middle-Boxes Considerations ..............................88
      15.3. Operation and Management Considerations ..................89
      15.4. Other Considerations .....................................90
   16. Security Considerations .......................................91
      16.1. Interaction with IPSec ...................................93
      16.2. Residual Threats .........................................94
   17. IANA Considerations ...........................................95
   18. Acknowledgements ..............................................97
   19. References ....................................................97
      19.1. Normative References .....................................97
      19.2. Informative References ...................................97
   Appendix A.  Possible Protocol Extensions ........................100
   Appendix B.  Simplified STATE Machine ............................101
      B.1.  Simplified STATE Machine Diagram ........................108
   Appendix C.  Context Tag Reuse ...................................109
      C.1.  Context Recovery ........................................109
      C.2.  Context Confusion .......................................109
      C.3.  Three-Party Context Confusion .........................110
      C.4.  Summary .................................................110
   Appendix D.  Design Alternatives .................................111
      D.1.  Context Granularity .....................................111
      D.2.  Demultiplexing of Data Packets in Shim6 Communications ..111
        D.2.1.   Flow Label .........................................112
        D.2.2.   Extension Header ...................................115
      D.3.  Context-Loss Detection ................................115
      D.4.  Securing Locator Sets ...................................117
      D.5.  ULID-Pair Context-Establishment Exchange ............120
      D.6.  Updating Locator Sets ...................................121
      D.7.  State Cleanup ...........................................122

1. Introduction โœจ

okay bestie, so this doc describes a layer 3 shim approach and protocol that gives you locator agility below the transport protocols ๐Ÿฆ‹. The goal is multihoming for IPv6 with failover and load-sharing energy [11], and it doesn't need a multihomed site to have a provider-independent IPv6 address announced in the global IPv6 routing table. ๐Ÿ’…

Hosts in a site with several provider-allocated IPv6 address prefixes use the Shim6 protocol from this document to set up state with peer hosts. That state can later be used to fail over to a different locator pair if the original one stops working. (The term locator is defined in Section 2 ๐ŸŒธ.)

Shim6 is a site-multihoming solution, meaning existing communication can keep going when a site with multiple connections to the Internet loses some of them, or something further upstream goes down. The thing is, Shim6 processing happens in individual hosts, not through site-wide mechanisms ๐Ÿซถ.

We assume redirection attacks are prevented using Hash-Based Addresses (HBA) as defined in [3] ๐Ÿ”.

The reachability and failure-detection mechanisms, including how a new working locator pair gets discovered after a failure, are specified in RFC 5534 [4]. This document allocates message types and option types for that sub-protocol, and leaves the message and option formats, plus the protocol behavior, to RFC 5534 ๐Ÿ“ฆ.

1.1. Goals

okay so the goals for this approach are to:

  • Preserve established communications when certain classes of failures happen, for example, TCP connections and UDP streams ๐Ÿ’–.
  • Have minimal impact on upper-layer protocols in general, and on transport protocols and applications in particular ๐ŸŽ€.
  • Address the security threats in [15] through a combination of the HBA/CGA approach specified in RFC 5535 [3] and the techniques described in this document ๐Ÿ”ฅ.
  • Not require an extra roundtrip up front to set up shim-specific state. Instead, let the upper-layer traffic (e.g., TCP) flow as normal, and defer setting up the shim state until some number of packets have been exchanged โœจ.
  • Take advantage of multiple locators/addresses for load spreading, so that different sets of communication to a host (e.g., different connections) might use different locators of that host. Note that this might cause load to be spread unevenly, which is why we use the term "load spreading" instead of "load balancing" ๐ŸŒˆ. This capability might enable some forms of traffic engineering, but the details for traffic engineering, including what requirements can be satisfied, are not specified in this document. They form part of potential extensions to this protocol ๐Ÿงš.

1.2. Non-Goals

the problem we're actually trying to solve is site multihoming, with the ability for the set of site prefixes to change over time because of site renumbering ๐Ÿ“. We also assume those changes to the set of locator prefixes can be relatively slow and managed: slow enough to let updates to the DNS propagate, since the protocol defined here depends on the DNS to find the appropriate locator sets ๐Ÿ•ฐ๏ธ.

BUT, it's an explicit non-goal to make communication survive a renumbering event, which is when all the locators of a host change to a new set of locators ๐Ÿ™ˆ. This proposal also doesn't try to solve the related problem of host mobility. However, it might turn out that the Shim6 protocol can be a useful component for future host mobility solutions, for example, for route optimization ๐Ÿฆ‹.

Finally, this proposal does not try to provide a new network-level or transport-level identifier name space that's separate from the current IP address name space. Honestly, a concept like that would be useful to upper-layer protocols (ULPs) and applications, especially if the management burden were negligible and there were an efficient yet secure way to map from identifiers to locators. But a name space like that isn't necessary to solve the multihoming problem, and it doesn't seem to help with it either ๐Ÿ’€.

The Shim6 proposal doesn't fully separate the identifier and locator functions that have traditionally been overloaded in the IP address. Still, throughout this document, the term "identifier" or, more specifically, upper-layer identifier (ULID), refers to the identifying function of an IPv6 address. "Locator" refers to the network-layer routing and forwarding properties of an IPv6 address ๐Ÿ’œ.

1.3. Locators as Upper-Layer Identifiers (ULID)

this is the fun part ๐Ÿซ . The approach here doesn't introduce a new identifier name space. Instead, it uses the locator selected during the initial contact with the remote peer as the preserved upper-layer identifier (ULID). Sure, the selected network-level locators might change over time (in response to failures when using the original locator), but the upper-level protocol stack elements keep using that same upper-level identifier without any change ๐ŸŽ€.

This means ULID selection is performed as today's default address selection, as specified in RFC 3484 [7]. Some extensions are needed to RFC 3484 so it can try different source addresses, whether or not the Shim6 protocol is used, as outlined in [9]. Underneath, and transparently, the multihoming shim selects working locator pairs, with the initial locator pair being the ULID pair. If communication later fails, the shim can test and select alternate locators ๐Ÿ”„. A later section discusses the issues that come up when the selected ULID isn't working at first, which creates the need to switch locators up front ๐Ÿ‘€.

Using one of the locators as the ULID has certain benefits for applications that have long-lived session state or that perform callbacks or referrals, because both the Fully Qualified Domain Name (FQDN) and the 128-bit ULID work as handles for the applications ๐Ÿ’–.

Still, using a single 128-bit ULID doesn't provide seamless communication when that locator is unreachable. See [18] for further discussion of the application implications ๐Ÿ˜ญ.

There has been some discussion about using non-routable addresses, such as Unique-Local Addresses (ULAs) [14], as ULIDs in a multihoming solution. This document doesn't specify all aspects of that, but it is believed the approach can be extended to handle the non-routable address case. For example, the protocol already needs to handle ULIDs that are not initially reachable, so the same mechanism can handle ULIDs that are permanently unreachable from outside their site ๐ŸŒธ. The open question is how to make the protocol perform well when the ULID is known a priori to be unreachable (e.g., the ULID is a ULA), for instance by avoiding any timeouts and retries in that case โฑ๏ธ. Plus, one would need to understand how ULAs would be entered in the DNS, so there's no performance impact on existing, non-Shim6-aware IPv6 hosts that might try to communicate with the (unreachable) ULA ๐Ÿง.

1.4. IP Multicast

okay so IP multicast requires that the IP Source Address field contain a topologically correct locator for the interface used to send the packet. That's because IP multicast routing uses both the source address and the destination group to decide where to forward the packet ๐Ÿ—บ๏ธ. In particular, IP multicast routing needs to be able to do the Reverse Path Forwarding (RPF) check. (This isn't much different from the situation with widely implemented ingress filtering [6] for unicast.)

In theory it would be possible to apply the shim re-mapping of the IP address fields between ULIDs and locators. But the fact that all the multicast receivers would need to know the mapping to do that makes the approach difficult in practice ๐Ÿ˜ตโ€๐Ÿ’ซ. So it makes sense for multicast ULPs to operate directly on locators and not use the shim. This is a pretty natural fit for protocols that use RTP [10], since RTP already has an explicit identifier in the form of the synchronization source (SSRC) field in the RTP headers. That means the actual IP address fields aren't important to the application ๐Ÿงš.

In summary, IP multicast will not need the shim to remap the IP addresses ๐ŸŒˆ.

This doesn't stop the receiver of multicast from changing its locators, since the receiver isn't explicitly identified. The destination address is a multicast address, not the unicast locator of the receiver ๐Ÿซถ.

1.5. Renumbering Implications

as we said above, this approach does not try to make communication survive renumbering in the general case ๐Ÿ™…โ€โ™€๏ธ.

When a host gets renumbered, the effect is that one or more locators become invalid, and zero or more locators get added to the host's network interface. This means the set of locators used in the shim will change. The shim can handle that as long as not all the original locators become invalid at the same time. The shim's ability to handle this also depends on how long it takes to update the DNS and for those updates to propagate โณ.

But IP addresses are also used as ULIDs, and making communication survive locators becoming invalid can potentially cause some confusion at the upper layers ๐Ÿ˜ฌ. A ULID might be used with a different locator over time, which opens up the possibility that communication between two ULIDs keeps working after one or both of those ULIDs are no longer reachable as locators, for example because of a renumbering event. That opens up the possibility that the ULID (or at least the prefix it's based on) gets reassigned to another site while it's still being used, with another locator, for existing communication ๐Ÿ˜ฑ.

In the worst case, we could end up with two separate hosts using the same ULID while both of them are communicating with the same host ๐Ÿ’€.

This potential source of confusion is avoided by requiring that any communication using a ULID MUST be terminated when the ULID becomes invalid (due to the underlying prefix becoming invalid) ๐Ÿšซ. This behavior can be accomplished by explicitly discarding the shim state when the ULID becomes invalid. The context-recovery mechanism will then make the peer aware that the context is gone and that the ULID is no longer present at the same locator(s) ๐ŸŽ€.

1.6. Placement of the Shim ๐Ÿฆ‹

okay so the big question is where this thing lives in the stack ๐Ÿ‘€ the answer is: the proposal puts a multihoming shim layer inside the IP layer, aka below the ULPs (see Figure 1). that's how ULPs stay independent ๐Ÿ’…

                             -----------------------
                             | Transport Protocols |
                             -----------------------

                          -------------- -------------    IP endpoint
                          | Frag/reass | | Dest opts |    sub-layer
                          -------------- -------------

                              ---------------------
                              | Shim6 shim layer  |
                              ---------------------

                                     ------               IP routing
                                     | IP |               sub-layer
                                     ------

                         Figure 1: Protocol Stack

the shim acts like it's attached to an extension header that sits after any routing-related headers (think hop-by-hop options) ๐ŸŽ€ BUT, when the locator pair is the ULID pair, there's no data that needs to go in an extension header, so โœจ none is needed in that case.

the Fragmentation header sits above the shim, and this is the clever part ๐Ÿง  if broken multi-path routing sends different fragments down different paths (so potentially different source locators), reassembly still stays robust ๐Ÿ”ฅ so the shim goes between the IP endpoint sublayer (the one doing fragmentation and reassembly) and the IP routing sublayer (the one picking the next hop and interface for outgoing packets).

applications and upper-layer protocols only ever use ULIDs ๐ŸŒธ the Shim6 layer maps them to and from different locators. to do that, it keeps ULID-pair context state per ULID pair, meaning the state covers every ULP connection between that pair ๐Ÿ’œ the mapping happens consistently on both the sender and the receiver, so the ULPs see packets that look like they were sent with ULIDs end to end, even though the packets are actually carrying locators in the IP address fields, and even though the transmitting Shim6 layer might change those locators ๐Ÿซถ

the context state is kept per remote ULID, which is roughly per peer host, and NOT at any finer granularity ๐Ÿ™ˆ it's totally independent of the ULPs and their connections. the one exception: the forking capability lets Shim6-aware ULPs use more than one locator pair at a time for a single ULID pair โœจ

    ----------------------------          ----------------------------
    | Sender A                 |          | Receiver B               |
    |                          |          |                          |
    |     ULP                  |          |     ULP                  |
    |      | src ULID(A)=L1(A) |          |      ^                   |
    |      | dst ULID(B)=L1(B) |          |      | src ULID(A)=L1(A) |
    |      v                   |          |      | dst ULID(B)=L1(B) |
    |   multihoming shim       |          |   multihoming shim       |
    |      | src L2(A)         |          |      ^                   |
    |      | dst L3(B)         |          |      | src L2(A)         |
    |      v                   |          |      | dst L3(B)         |
    |      IP                  |          |      IP                  |
    ----------------------------          ----------------------------
           |                                     ^
           ------- cloud with some routers -------

                  Figure 2: Mapping with Changed Locators

because the mapping is consistent, the ULPs are completely unaffected ๐Ÿฆ‹ pseudo-header checksums and connection identification keep working exactly as they always did ๐Ÿ’…

conceptually, you can picture it like this: both ULIDs AND locators are in every packet, and then a header-compression trick removes the need to carry the ULIDs once the compression state has been set up ๐Ÿงš the receiver still needs to rebuild the packet with the correct ULIDs, so the data packets include a "compression tag" ๐Ÿท๏ธ it tells the receiver which context to use for decompression, for when the locator pair alone can't uniquely identify the context ๐ŸŒˆ

there are different kinds of interactions between the Shim6 layer and other protocols ๐Ÿ“ they depend on how those protocols use addresses, and how the Shim6 mapping changes that. a detailed breakdown, covering the Stream Control Transmission Protocol (SCTP), mobile IP (MIP), and Host Identity Protocol (HIP), lives in [19] ๐Ÿ“š some apps might want a richer relationship with the Shim6 sublayer, so there's an API [23] for greater control and info exchange for the apps that need it ๐Ÿ‘‘


1.7. Traffic Engineering ๐Ÿšฆ

ngl this one is a little bit of a mystery ๐Ÿ™ˆ at the time of writing, it's not clear what traffic engineering requirements make sense for Shim6, because they have to do two things at once: give some useful behavior AND be doable with a host-to-host locator agility mechanism like Shim6 ๐Ÿ’€

here's the vibe: a scalable multihoming mechanism separates the locator function of an IP address from its identifying function, so every host ends up with multiple locators ๐ŸŽ€ that means, at least for the first contact, the remote peer application (or whatever layer is working on its behalf) is the one that picks an initial ULID, and that ULID automatically becomes the initial locator โœจ in Shim6, that choice is made by applying RFC 3484 address selection ๐Ÿ’…

this is super different from the usual IPv4 multihoming setup, where the site has a single IP address prefix ๐ŸŒธ in that case the peer does no destination address selection at all, since there's only one prefix to pick from.

so in "single prefix multihoming," the site (and often its upstream ISPs) can use BGP to steer the ingress path into the site ๐Ÿ›ฃ๏ธ and that control does NOT exist by itself in "multiple prefix multihoming" approaches like Shim6 ๐Ÿ˜ญ it's conceivable that extensions letting a site or provider guide host-based mechanisms could be built someday ๐Ÿ”ฎ but traffic engineering via BGP, MPLS, or similar techniques can still be applied to traffic on each individual prefix. Shim6 doesn't take that capability away ๐Ÿซถ what it does add is extra ways for hosts to choose between prefixes ๐Ÿฆ‹

โš ๏ธ heads up: these capabilities carry some risk of non-optimal behavior when more than one mechanism tries to fix a problem at the same time. BUT this isn't necessarily something Shim6 causes on its own! IPv6 already has a more constrained version of this via support for multiple prefixes and address-selection rules for starting new communications ๐ŸŒˆ even IPv4 hosts with multiple interfaces can have limited ability to pick which interface they communicate on, and upper layers can pick different addresses too ๐Ÿ’œ

overall, the expectation is that Shim6 fits best in relatively small sites and individual hosts where BGP-style traffic engineering is unavailable or unlikely ๐Ÿ  if it's run with provider-independent addressing, it could even be harmful, considering how fast the global routing table is growing ๐Ÿ“ˆ

the protocol includes a placeholder, the Locator Preferences option, that hosts can use to express priority and weight values for each locator ๐Ÿง it's ONLY a placeholder for traffic engineering though. to use it in a large site, there'd need to be a way for the host to find out what preference values to use, either statically (e.g., some new DHCPv6 option) or dynamically ๐Ÿงš

so yep, traffic engineering is listed as a possible extension in Appendix A ๐Ÿ“


2. Terminology ๐Ÿ’œ

the key words in this document are the ones you'd expect, and they mean exactly what the standard says they mean ๐Ÿค“ the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [1] ๐Ÿซถ

2.1. Definitions ๐Ÿ’…

okay so this section drops a bunch of new terms, and they're all going to matter later ๐ŸŽ€

  • upper-layer protocol (ULP): a protocol sitting right above IP ๐Ÿง Think transport stuff like TCP and UDP, control stuff like ICMP, routing stuff like OSPF, and even lower-layer or Internet protocols that get "tunneled" over (aka encapsulated in) IP, like the Internet Packet Exchange (IPX), AppleTalk, or IP itself ๐ŸŒˆ
  • interface: a node's attachment to a link ๐Ÿ”Œ
  • address: an IP-layer name that has topological meaning and works as a unique identifier for an interface. It's 128 bits ๐Ÿฆ‹ This doc only uses the word "address" when it isn't clear whether something is a locator or an identifier.
  • locator: an IP-layer topological name for an interface or a set of interfaces, and it's 128 bits too. Locators ride in the IP address fields as packets travel across the network ๐Ÿš€
  • identifier: an IP-layer name for an IP-layer endpoint. The transport endpoint name depends on the transport protocol and would usually include the IP identifier plus a port number ๐Ÿ’œ
NOTE: This proposal does not specify any new form of IP-layer identifier, but still separates the identifying and locating properties of the IP addresses. ๐Ÿซถ
  • upper-layer identifier (ULID): an IP address picked for talking to a peer, to be used by the upper-layer protocol. It's 128 bits ๐Ÿ”ฅ It's used for pseudo-header checksum computation and connection identification in the ULP. Different sets of communication to a host (e.g., different connections) might use different ULIDs so the load can spread around ๐ŸŒธ

Since the ULID is just one of the node's IP locators/addresses, there's no need for a separate name space or allocation mechanisms. Iconic efficiency ๐Ÿ‘‘

  • address field: the Source and Destination Address fields in the IPv6 header. The way IPv6 is currently specified, these fields carry "addresses." If identifiers and locators get separated, these fields will hold locators for packets on the wire โœจ
  • FQDN: Fully Qualified Domain Name
  • ULID-pair context: the state the multihoming shim keeps between a pair of upper-layer identifiers. The context is identified by a Context Tag for each direction of the communication, and also by a ULID-pair and a Forked Instance Identifier (more on that below) ๐ŸŽ€
  • Context Tag: each end of the context allocates one for the context. It's how the two ends uniquely link received control packets and Shim6 Payload Extension headers to the right context ๐Ÿท๏ธ
  • current locator pair: each end has one, and it's what gets used to send packets to the peer. The two ends might be using different current locator pairs, and that's fine ๐Ÿฆ‹
  • default context: at the sending end, the shim uses the ULID pair (passed down from the ULP) to find the context for that pair. So normally a host can have at most one context per ULID pair. This is called the "default context" ๐Ÿ’–
  • context forking: a mechanism that lets ULPs aware of multiple locators use separate contexts for the same ULID pair, so they can use different locator pairs for different communication to the same ULID. Forking creates more than just the default context for a ULID pair ๐Ÿงš
  • Forked Instance Identifier (FII): to handle context forking, a context is identified by a ULID pair and a Forked Context Identifier. The default context has an FII of zero ๐ŸŒˆ
  • initial contact: the pre-shim communication when a ULP decides to start talking to a peer by sending and receiving ULP packets. Usually this doesn't kick off any shim operations, since the shim can put off context establishment until some arbitrary, later point in time ๐Ÿซ 
  • Hash-Based Addresses (HBA): a form of IPv6 address where the interface ID is derived from a cryptographic hash of all the prefixes assigned to the host. See [3]. ๐Ÿ”
  • Cryptographically Generated Addresses (CGA): a form of IPv6 address where the interface ID is derived from a cryptographic hash of the public key. See [2]. ๐Ÿ”‘
  • CGA Parameter Data Structure (PDS): the info that CGA and HBA exchange so the peer knows how the interface ID was computed. See [2] and [3]. ๐Ÿ“œ

2.2. Notational Conventions โœจ

A, B, and C are hosts. X is a potentially malicious host ๐Ÿ‘€

FQDN(A) is the Fully Qualified Domain Name for A.

Ls(A) is the locator set for A, which is made up of the locators L1(A), L2(A), ... Ln(A). The locator set isn't ordered in any particular way, other than maybe whatever order the DNS hands back. A host might form different locator sets that contain different subnets of the host's IP addresses, and in some cases that's necessary for security reasons. See Section 16.1. ๐Ÿ›ก๏ธ

ULID(A) is an upper-layer identifier for A. In this proposal, ULID(A) is always one member of A's locator set ๐Ÿ’…

CT(A) is a Context Tag assigned by A ๐Ÿท๏ธ

STATE (in uppercase) refers to the specific state of the state machine described in Section 6.2 ๐Ÿง 


2.3. Conceptual ๐Ÿง 

This document also uses internal conceptual variables to describe protocol behavior, and external variables that an implementation must let system administrators change. The specific variable names, how their values change, and how their settings influence protocol behavior are given to demonstrate protocol behavior. An implementation isn't required to have them in the exact form described here, as long as its external behavior is consistent with what this document describes. See Section 6 for a description of the conceptual data structures ๐ŸŽ€


3. Assumptions โœจ

The design intent is that Shim6 can handle path failures no matter how many IP addresses (locators) the two communicating hosts have, and no matter which host notices the failure ๐Ÿฆ‹

Picture this: both A and B have active Shim6 state, but A has only one locator while B has several. B might be trying to send a packet to A and notice a failure with the current locator pair. Since B has multiple locators, it presumably has multiple ISPs, and so it likely has alternate egress paths toward A ๐ŸŒˆ B can't change the destination address (that's A's locator), since A only has one. But B may need to change the source address to make sure the packet gets delivered ๐Ÿ’Œ

In lots of cases, normal IP routing will send packets down a path toward the correct, currently working egress. In some cases a path may get picked based on the source address, which means B will need to pick a source address that matches the egress that's currently working. How routing gets done is beyond the scope of this document ๐Ÿ—บ๏ธ

Also, when a site's ISPs do ingress filtering based on packet source addresses, Shim6 assumes that packets sent with different source and destination combinations have a reasonable chance of getting through the relevant ISP's ingress filters. This can be done in a few ways (all outside the scope of this document), like having the ISPs relax their ingress filters, or picking the egress so it matches the IP source address prefix ๐Ÿ™ˆ If one egress path has failed but another is working fine, the packet's source (node B in the previous paragraph) may need to pick a source address that matches the working egress, so the packet gets past the ISP's ingress filters ๐Ÿšฆ

The Shim6 approach assumes there are no IPv6-to-IPv6 NATs on the paths. In other words, the two ends can exchange their own notion of their IPv6 addresses, and those addresses will also make sense to their peer ๐Ÿ’–

The security of the Shim6 protocol relies on the use of Hash-Based Addresses (HBA) [3] and/or Cryptographically Generated Addresses (CGA) [2] ๐Ÿ” If HBAs are used, all the addresses assigned to the host that are included in the Shim6 protocol (either as a locator or as a ULID) must be part of the same HBA set. If CGAs are used, the address used as the ULID must be a CGA, but the other addresses used as locators don't need to be CGAs or HBAs. It's worth noting that it's perfectly acceptable to run the Shim6 protocol between a host that has multiple locators and another host that has a single IP address. In that case, the address of the host with a single address doesn't need to be an HBA or a CGA ๐Ÿซถ

4. Protocol Overview โœจ

okay bestie, here's the whole Shim6 life story in order ๐Ÿ’– The protocol runs in several phases over time, and it goes like this:

  • Initial contact ๐Ÿฆ‹ An application on host A decides to contact an application on host B using some upper-layer protocol. This results in the ULP on host A sending packets to host B. We call this the initial contact. Assuming the IP addresses selected by default address selection [7] and its extensions [9] work, then there is no action by the shim at this point in time. Any shim context establishment can be deferred until later.
  • The "okay we need protection now" moment ๐ŸŒธ Some heuristic on A or B (or both) determines that it is appropriate to pay the Shim6 overhead to make this host-to-host communication robust against locator failures. For instance, this heuristic might be that more than 50 packets have been sent or received, or that there was a timer expiration while active packet exchange was in place. This makes the shim initiate the 4-way, context-establishment exchange. The purpose of this heuristic is to avoid setting up a shim context when only a small number of packets is exchanged between two hosts.

As a result of this exchange, both A and B will know a list of locators for each other.

If the context-establishment exchange fails, the initiator will then know that the other end does not support Shim6, and will continue with standard (non-Shim6) behavior for the session.

  • Business as usual ๐Ÿ’… Communication continues without any change for the ULP packets. In particular, there are no Shim6 Extension headers added to the ULP packets, since the ULID pair is the same as the locator pair. In addition, there might be some messages exchanged between the shim sublayers for (un)reachability detection.
  • Plot twist: something fails ๐Ÿ˜ญ At some point in time, something fails. Depending on the approach to reachability detection, there might be some advice from the ULP, or the shim (un)reachability detection might discover that there is a problem.

At this point in time, one or both ends of the communication need to probe the different alternate locator pairs until a working pair is found, and then switch to using that locator pair.

  • The switcheroo ๐Ÿ”ฅ Once a working alternative locator pair has been found, the shim will rewrite the packets on transmit and tag the packets with the Shim6 Payload Extension header, which contains the receiver's Context Tag. The receiver will use the Context Tag to find the context state, which will indicate which addresses to place in the IPv6 header before passing the packet up to the ULP. The result is that, from the perspective of the ULP, the packet passes unmodified end-to-end, even though the IP routing infrastructure sends the packet to a different locator. Iconic, honestly ๐Ÿ‘‘
  • Keeping an eye on the new route ๐Ÿงš The shim (un)reachability detection will monitor the new locator pair as it monitored the original locator pair, so that subsequent failures can be detected.
  • Knowing it's broken before anyone asks ๐Ÿ™ˆ In addition to failures detected based on end-to-end observations, one endpoint might know for certain that one or more of its locators is not working. For instance, the network interface might have failed or gone down (at layer 2), or an IPv6 address might have become deprecated or invalid. In such cases, the host can signal its peer that trying this address is no longer recommended. This triggers something similar to a failure handling, and a new working locator pair must be found.

The protocol also has the ability to express other forms of locator preferences. A change in any preference can be signaled to the peer, which will have made the peer record the new preferences. A change in the preferences might optionally make the peer want to use a different locator pair. In this case, the peer follows the same locator switching procedure as after a failure (by verifying that its peer is indeed present at the alternate locator, etc).

  • Cleaning up the closet ๐Ÿ“ When the shim thinks that the context state is no longer used, it can garbage collect the state; there is no coordination necessary with the peer host before the state is removed. There is a recovery message defined to be able to signal when there is no context state, which can be used to detect and recover from both premature garbage collection as well as from complete state loss (crash and reboot) of a peer.

The exact mechanism to determine when the context state is no longer used is implementation dependent. For example, an implementation might use the existence of ULP state (where known to the implementation) as an indication that the state is still used, combined with a timer (to handle ULP state that might not be known to the shim sublayer) to determine when the state is likely to no longer be used.

NOTE 1: The ULP packets in Shim6 can be carried completely unmodified as long as the ULID pair is used as the locator pair. After a switch to a different locator pair, the packets are "tagged" with a Shim6 Extension header so that the receiver can always determine the context to which they belong. This is accomplished by including an 8-octet Shim6 Payload Extension header before the (extension) headers that are processed by the IP endpoint sublayer and ULPs. If, subsequently, the original ULIDs are selected as the active locator pair, then the tagging of packets with the Shim6 Extension header is no longer necessary.

4.1. Context Tags ๐ŸŽ€

okay so a context between two hosts is actually a context between two ULIDs ๐Ÿซถ The context is identified by a pair of Context Tags. Each end gets to allocate a Context Tag, and once the context is established, most Shim6 control messages contain the Context Tag that the receiver of the message allocated. Thus, at a minimum, the combination of <peer ULID, local ULID, local Context Tag> has to uniquely identify one context.

But here's the twist ๐Ÿฆ‹ since the Shim6 Payload Extension headers are demultiplexed without looking at the locators in the packet, the receiver will need to allocate Context Tags that are unique for all its contexts. The Context Tag is a 47-bit number (the largest that can fit in an 8-octet extension header), while preserving one bit to differentiate the Shim6 signaling messages from the Shim6 header included in data packets, allowing both to use the same protocol number. Very clever, no cap โœจ

The mechanism for detecting a loss of context state at the peer assumes that the receiver can tell the packets that need locator rewriting, even after it has lost all state (e.g., due to a crash followed by a reboot). This is achieved because, after a rehoming event, the packets that need receive-side rewriting carry the Shim6 Payload Extension header. Main character energy ๐Ÿ’œ


4.2. Context Forking ๐ŸŒˆ

It has been asserted that it will be important for future ULPs -- in particular, future transport protocols -- to be able to control which locator pairs are used for different communication. For instance, host A and host B might communicate using both Voice over IP (VoIP) traffic and ftp traffic, and those communications might benefit from using different locator pairs. However, the basic Shim6 mechanism uses a single current locator pair for each context; thus, a single context cannot accomplish this. Lowkey a problem ๐Ÿ™ˆ

For this reason, the Shim6 protocol supports the notion of context forking. This is a mechanism by which a ULP can specify (using some API not yet defined) that a context, e.g., the ULID pair <A1, B2>, should be forked into two contexts. In this case, the forked-off context will be assigned a non-zero Forked Instance Identifier, while the default context has FII zero.

The Forked Instance Identifier (FII) is a 32-bit identifier that has no semantics in the protocol other than being part of the tuple that identifies the context. For example, a host might allocate FIIs as sequential numbers for any given ULID pair. ๐Ÿงš

No other special considerations are needed in the Shim6 protocol to handle forked contexts. โœจ

Note that forking as specified does NOT allow A to be able to tell B that certain traffic (a 5-tuple?) should be forked for the reverse direction. The Shim6 forking mechanism as specified applies only to the sending of ULP packets. If some ULP wants to fork for both directions, it is up to the ULP to set this up and then instruct the shim at each end to transmit using the forked context. Bestie, that's a whole separate mission ๐ŸŽ€


4.3. API Extensions ๐Ÿ“

Several API extensions have been discussed for Shim6, but their actual specification is out of scope for this document. The simplest one would be to add a socket option to be able to have traffic bypass the shim (not create any state and not use any state created by other traffic). This could be IPV6_DONTSHIM. Such an option would be useful for protocols, such as DNS, where the application has its own failover mechanism (multiple NS records in the case of DNS) and using the shim could potentially add extra latency with no added benefits. Honestly so practical ๐Ÿ’…

Some other API extensions are discussed in Appendix A. The actual API extensions are defined in [23].


4.4. Securing Shim6 ๐Ÿ”ฅ

Okay, the security part is seriously important, so pay attention ๐Ÿ’€ The mechanisms are secured using a combination of techniques:

  • ๐Ÿ›ก๏ธ The HBA technique [3] for verifying the locators to prevent an attacker from redirecting the packet stream to somewhere else.
  • ๐Ÿ›ก๏ธ Requiring a Reachability Probe+Reply (defined in [4]) before a new locator is used as the destination, in order to prevent 3rd party flooding attacks.
  • ๐Ÿ›ก๏ธ The first message does not create any state on the responder. Essentially, a 3-way exchange is required before the responder creates any state. This means that a state-based DoS attack (trying to use up all memory on the responder) at least provides an IPv6 address that the attacker was using.
  • ๐Ÿ›ก๏ธ The context-establishment messages use nonces to prevent replay attacks and to prevent off-path attackers from interfering with the establishment.
  • ๐Ÿ›ก๏ธ Every control message of the Shim6 protocol, past the context establishment, carries the Context Tag assigned to the particular context. This implies that an attacker needs to discover that Context Tag before being able to spoof any Shim6 control message. Such discovery probably requires any potential attacker to be along the path in order to sniff the Context Tag value. The result is that through this technique, the Shim6 protocol is protected against off-path attackers. Off-path attackers said "not me" ๐Ÿ™…โ€โ™€๏ธ๐Ÿ‘‘

4.5. Overview of Shim Control Messages โœจ

okay so Shim6 context establishment is a four-message handshake: I1, R1, I2, R2 ๐Ÿ’– Normally the initiator and responder send them in that order. But if both ends try to set up context state at the same time for the same ULID pair, their I1 messages can cross in flight and trigger an immediate R2 message ๐Ÿ”ฅ (fun fact: these names are borrowed from HIP [20] ๐Ÿฆ‹).

R1bis and I2bis are also defined ๐Ÿงš They're used to recover a context after it has been lost. An R1bis message is sent when a Shim6 control or Shim6 Payload Extension header shows up and the receiver has no matching context state. When that happens, the receiver re-creates the Shim6 context using I2bis and R2 messages. It's giving self-healing ๐Ÿ’…

The peers normally swap their lists of locators as part of the context-establishment exchange. But that set of locators can be dynamic ๐ŸŒˆ That's why there are Update Request and Update Acknowledgement messages, plus a Locator List option.

Even when the locator list stays fixed, a host might notice that some preferences have changed ๐Ÿ‘€ For example, it might spot a locally visible failure that means some locator(s) are no longer usable. For that, the Update Request message carries a Locator Preferences option.

The mechanism for (un)reachability detection is called Forced Bidirectional Communication (FBD) ๐Ÿ’œ FBD uses a Keepalive message, which gets sent when a host has received packets from its peer but hasn't yet sent any packets from its ULP to the peer. The message type is reserved in this document, but the message format and processing rules are specified in [4].

Also, once the context is established and something fails, you need a quick way to probe the set of locator pairs and efficiently find one that works ๐Ÿ” This document reserves a Probe message type, with the packet format and processing rules specified in [4]. Main character energy for sure โญ

The Probe and Keepalive messages above assume we already have an established ULID-pair context. But communication can fail during the initial contact, meaning while the application or transport protocol is still trying to get things going ๐Ÿ˜ญ That's handled by the ULP's own mechanisms, which try different address pairs as specified in [7] and [9]. In future versions, with a richer API between the ULP and the shim, the shim might be able to help speed up finding a working locator pair during initial contact. That's for further study ๐Ÿ™ˆ

4.6. Extension Header Order

okay this one is a little spicy ๐ŸŒถ๏ธ The shim sits between the IP endpoint sublayer and the IP routing sublayer. So the Shim header goes before any Endpoint Extension headers (Fragmentation headers, Destination Options header, AH, ESP) but after any routing-related headers (Hop-by-Hop Extensions header, Routing header, and a Destinations Options header that comes before a Routing header). When tunneling is involved, whether that's IP-in-IP or the special form Mobile IPv6 uses (with Home Address options and Routing header type 2), you get to choose whether the shim applies inside the tunnel or outside it. That choice changes where the Shim6 header lands ๐ŸŽ€

In most cases IP-in-IP tunnels are used as a routing technique, so it makes sense to apply them on the locators. That means the sender inserts the Shim6 header after any IP-in-IP encapsulation. This is what happens naturally when routers apply IP-in-IP encapsulation ๐Ÿ“ So the packets look like this:

  • Outer IP header
  • Inner IP header
  • Shim6 Extension header (if needed)
  • ULP

But the shim can also be used to create "shimmed tunnels" ๐Ÿฆ‹ That's where an IP-in-IP tunnel uses the shim to switch the tunnel endpoint addresses between different locators. In that case the packets look like this:

  • Outer IP header
  • Shim6 Extension header (if needed)
  • Inner IP header
  • ULP

In any case, the receiver behavior is well-defined: a receiver processes the Extension headers in order โœจ However, the precise interaction between Mobile IPv6 and Shim6 is for further study. It might make sense to have Mobile IPv6 operate on locators as well, which would mean the shim is layered on top of the MIPv6 mechanism. Layers upon layers, bestie ๐Ÿง

5. Message Formats ๐ŸŽ€

okay so all the Shim6 messages are carried using a new IP protocol number, 140 ๐Ÿ’œ Each Shim6 message has a common header with some fixed fields, followed by type-specific fields.

The Shim6 messages are structured as an IPv6 Extension header, because the Shim6 Payload Extension header is used to carry ULP packets after a locator switch ๐ŸŒธ The Shim6 control messages use the same extension header formats too. That means a single "protocol number" has to be allowed through firewalls for Shim6 to work across the firewall. Efficient, no cap ๐Ÿ’…

5.1. Common Shim6 Message Format

The first 17 bits of the Shim6 header are common to the Shim6 Payload Extension header and the control messages. It looks like this:

     0                   1
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Next Header  |  Hdr Ext Len  |P|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Next Header: The payload that follows this header.
  • Hdr Ext Len: 8-bit unsigned integer. Length of the Shim6 header in 8-octet units, not including the first 8 octets.
  • P: A single bit to distinguish Shim6 Payload Extension headers from control messages.

Shim6 signaling packets may not be larger than 1280 bytes ๐Ÿ“ That's the rule, including the IPv6 header and any intermediate headers between the IPv6 header and the Shim6 header. One way to meet it is to omit part of the locator address information if including it would make the packet bigger than 1280 bytes. Another option is option engineering, which means splitting the information you want to send across different Shim6 messages. An implementation may also impose administrative restrictions to avoid excessively large Shim6 packets, such as a limit on the number of locators to be used ๐Ÿซถ

5.2. Shim6 Payload Extension Header Format

The Shim6 Payload Extension header carries ULP packets where the receiver has to replace the content of the Source and/or Destination fields in the IPv6 header before passing the packet up to the ULP. So this extension header is required when the locator pair in use isn't the same as the ULID pair ๐Ÿฆ‹

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Next Header  |       0       |1|                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                      Receiver Context Tag                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Next Header: The payload that follows this header.
  • Hdr Ext Len: 0 (since the header is 8 octets).
  • P: Set to one. A single bit to distinguish this from the Shim6 control messages.
  • Receiver Context Tag: 47-bit unsigned integer. Allocated by the receiver to identify the context.

5.3. Common Shim6 Control Header

The common part of the header has a Next Header field and a Header Extension Length field that are consistent with the other IPv6 Extension headers. That's true even though the Next Header value is always "NO NEXT HEADER" for the control messages ๐ŸŒˆ

The Shim6 headers have to be a multiple of 8 octets, so the minimum size is 8 octets.

The common Shim6 Control message header looks like this:

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Next Header  |  Hdr Ext Len  |P|     Type    |Type-specific|S|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
    |                    Type-specific format                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Next Header: 8-bit selector. Normally set to NO_NXT_HDR (59).
  • Hdr Ext Len: 8-bit unsigned integer. Length of the Shim6 header in 8-octet units, not including the first 8 octets.
  • P: Set to zero. A single bit to distinguish this from the Shim6 Payload Extension header.
  • Type: 7-bit unsigned integer. Identifies the actual message from the table below. Type codes 0-63 will not trigger R1bis messages on a missing context, while codes 64-127 will trigger R1bis. ๐Ÿ‘€
  • S: A single bit set to zero that allows Shim6 and HIP to have a common header format yet still distinguishes between Shim6 and HIP messages.
  • Checksum: 16-bit unsigned integer. The checksum is the 16-bit one's complement of the one's complement sum of the entire Shim6 header message, starting with the Shim6 Next Header field and ending as indicated by the Hdr Ext Len. So when a payload follows the Shim6 header, the payload is NOT included in the Shim6 checksum. Also, unlike protocols like ICMPv6, there's no pseudo-header part in the checksum. That's what gives you locator agility without having to change the checksum โœจ
  • Type-specific: Part of the message that differs between message types.

Here's the message type table ๐Ÿ“‹

    +------------+----------------------------------------------------+
    | Type Value |                       Message                      |
    +------------+----------------------------------------------------+
    |      1     |  I1 (1st establishment message from the initiator) |
    |      2     |  R1 (1st establishment message from the responder) |
    |      3     |  I2 (2nd establishment message from the initiator) |
    |      4     |  R2 (2nd establishment message from the responder) |
    |      5     | R1bis (Reply to reference to non-existent context) |
    |      6     |          I2bis (Reply to an R1bis message)         |
    |     64     |                   Update Request                   |
    |     65     |               Update Acknowledgement               |
    |     66     |                      Keepalive                     |
    |     67     |                    Probe Message                   |
    |     68     |                    Error Message                   |
    +------------+----------------------------------------------------+

Table 1 ๐Ÿ’œ

5.4. I1 Message Format โœจ

okay bestie, the I1 message is the very first message in the context-establishment exchange ๐Ÿ’– it's the opener of the whole convo ๐Ÿฆ‹

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |       59      |  Hdr Ext Len  |0|  Type = 1   |   Reserved1 |0|
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |            Checksum           |R|                             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
 |                  Initiator Context Tag                        |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                    Initiator Nonce                            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 +                         Options                               +
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Here's the field rundown, no cap ๐ŸŒธ

  • Next Header: NO_NXT_HDR (59).
  • Hdr Ext Len: at least 1, since the header is 16 octets when there are no options ๐Ÿงš
  • Type: 1
  • Reserved1: a 7-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt.
  • R: a 1-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt.
  • Initiator Context Tag: a 47-bit field. The Context Tag that the initiator has allocated for the context ๐Ÿ“
  • Initiator Nonce: a 32-bit unsigned integer. A random number picked by the initiator, which the responder will return in the R1 message ๐ŸŽ€

The following options are defined for this message:

  • ULID pair: When the IPv6 source and destination addresses in the IPv6 header does not match the ULID pair, this option MUST be included. An example of this is when recovering from a lost context ๐Ÿ”ฅ
  • Forked Instance Identifier: When another instance of an existent context with the same ULID pair is being created, a Forked Instance Identifier option MUST be included to distinguish this new instance from the existent one ๐Ÿ‘‘

Future protocol extensions might define additional options for this message. The C-bit in the option format defines how such a new option will be handled by an implementation. See Section 5.15 โœจ


5.5. R1 Message Format ๐Ÿ’œ

the R1 message is the second message in the context-establishment exchange ๐Ÿฆ‹ the responder sends it in response to an I1 message, and here's the lowkey iconic part: it does this without creating any state specific to the initiator ๐Ÿซถ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |       59      |  Hdr Ext Len  |0|  Type = 2   |   Reserved1 |0|
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |            Checksum           |           Reserved2           |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                    Initiator Nonce                            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                    Responder Nonce                            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 +                         Options                               +
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The fields, bestie ๐Ÿ’…

  • Next Header: NO_NXT_HDR (59).
  • Hdr Ext Len: at least 1, since the header is 16 octets when there are no options ๐ŸŒˆ
  • Type: 2
  • Reserved1: a 7-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt.
  • Reserved2: a 16-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt.
  • Initiator Nonce: a 32-bit unsigned integer. Copied from the I1 message ๐ŸŒธ
  • Responder Nonce: a 32-bit unsigned integer. A number picked by the responder, which the initiator will return in the I2 message ๐Ÿงš

The following options are defined for this message:

  • Responder Validator: a variable length option. This option MUST be included in the R1 message. Typically, it contains a hash generated by the responder, which the responder uses together with the Responder Nonce value to verify that an I2 message is indeed sent in response to an R1 message, and that the parameters in the I2 message are the same as those in the I1 message ๐Ÿ”

Future protocol extensions might define additional options for this message. The C-bit in the option format defines how such a new option will be handled by an implementation. See Section 5.15 ๐Ÿ’–


5.6. I2 Message Format ๐ŸŒท

the I2 message is the third message in the context-establishment exchange ๐ŸŽ€ the initiator sends it in response to an R1 message, after checking the Initiator Nonce, etc. ๐Ÿ’…

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |       59      |  Hdr Ext Len  |0|  Type = 3   |   Reserved1 |0|
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |            Checksum           |R|                             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
 |                  Initiator Context Tag                        |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                    Initiator Nonce                            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                    Responder Nonce                            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                       Reserved2                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 +                         Options                               +
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Field check โœจ

  • Next Header: NO_NXT_HDR (59).
  • Hdr Ext Len: at least 2, since the header is 24 octets when there are no options ๐Ÿฆ‹
  • Type: 3
  • Reserved1: a 7-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt.
  • R: a 1-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt.
  • Initiator Context Tag: a 47-bit field. The Context Tag that the initiator has allocated for the context ๐Ÿ“
  • Initiator Nonce: a 32-bit unsigned integer. A random number picked by the initiator, which the responder will return in the R2 message ๐ŸŒˆ
  • Responder Nonce: a 32-bit unsigned integer. Copied from the R1 message ๐Ÿงš
  • Reserved2: a 32-bit field, reserved for future use. Zero on transmit. MUST be ignored on receipt. (Needed to make the options start on a multiple of 8 octet boundary.) ๐Ÿซถ

The following options are defined for this message:

  • Responder Validator: a variable length option. This option MUST be included in the I2 message and MUST be generated by copying the Responder Validator option received in the R1 message ๐Ÿ”
  • ULID pair: When the IPv6 source and destination addresses in the IPv6 header do not match the ULID pair, this option MUST be included. An example of this is when recovering from a lost context ๐Ÿ”ฅ
  • Forked Instance Identifier: When another instance of an existent context with the same ULID pair is being created, a Forked Instance Identifier option MUST be included to distinguish this new instance from the existent one ๐Ÿ‘‘
  • Locator List: Optionally sent when the initiator immediately wants to tell the responder its list of locators. When it is sent, the necessary HBA/CGA information for verifying the locator list MUST also be included ๐ŸŒธ
  • Locator Preferences: Optionally sent when the locators don't all have equal preference โญ
  • CGA Parameter Data Structure: This option MUST be included in the I2 message when the locator list is included so the receiver can verify the locator list ๐Ÿ’œ
  • CGA Signature: This option MUST be included in the I2 message when some of the locators in the list use CGA (and not HBA) for verification ๐Ÿ’€

Future protocol extensions might define additional options for this message. The C-bit in the option format defines how such a new option will be handled by an implementation. See Section 5.15 ๐ŸŒˆ

5.7. R2 Message Format

Okay bestie, the R2 message is the fourth message in the context-establishment exchange ๐Ÿ’–. The responder sends it back after getting an I2 message โœจ. R2 also shows up when both hosts send I1 messages at the same moment and the two cross in flight ๐Ÿฆ‹.

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       59      |  Hdr Ext Len  |0|  Type = 4   |   Reserved1 |0|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |R|                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                  Responder Context Tag                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Initiator Nonce                            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                         Options                               +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Here's the field rundown ๐ŸŽ€:

  • Next Header: it's NO_NXT_HDR (59).
  • Hdr Ext Len: at least 1, since the header is 16 octets when there are no options.
  • Type: 4.
  • Reserved1: a 7-bit field reserved for future use ๐Ÿ™ˆ. Set it to zero when you send it. It MUST be ignored on receipt.
  • R: a 1-bit field, also reserved for future use. Set it to zero when you send it. It MUST be ignored on receipt.
  • Responder Context Tag: a 47-bit field holding the Context Tag the responder allocated for the context.
  • Initiator Nonce: a 32-bit unsigned integer, copied from the I2 message.

These are the options defined for this message ๐Ÿ’…:

  • Locator List: optionally sent when the responder wants to tell the initiator its list of locators right away. When it's sent, the necessary HBA/CGA information for verifying the locator list MUST also be included.
  • Locator Preferences: optionally sent when the locators don't all have equal preference.
  • CGA Parameter Data Structure: included when the locator list is included, so the receiver can verify that list.
  • CGA Signature: included when some of the locators in the list use CGA (and not HBA) for verification.

Future protocol extensions might define more options for this message ๐ŸŒˆ. The C-bit in the option format decides how an implementation handles any new option it doesn't know yet. See Section 5.15.


5.8. R1bis Message Format

Okay so, if a host gets a packet carrying a Shim6 Payload Extension header, or a Shim6 control message with type code 64-127 (like an Update or Probe message), and it has no context state for the Context Tag in there, it will generate an R1bis message ๐Ÿ’€.

This message lets the sender of the packet that mentions the non-existent context re-establish it with a reduced context-establishment exchange ๐Ÿงš. Once the receiver gets the R1bis, it can rebuild the lost context by sending an I2bis message directly โœจ.

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       59      |  Hdr Ext Len  |0|  Type = 5   |   Reserved1 |0|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |R|                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                     Packet Context Tag                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Responder Nonce                            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                         Options                               +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Field time ๐Ÿ“:

  • Next Header: it's NO_NXT_HDR (59).
  • Hdr Ext Len: at least 1, since the header is 16 octets when there are no options.
  • Type: 5.
  • Reserved1: a 7-bit field reserved for future use. Set it to zero when you send it. It MUST be ignored on receipt.
  • R: a 1-bit field reserved for future use. Set it to zero when you send it. It MUST be ignored on receipt.
  • Packet Context Tag: a 47-bit unsigned integer. It's the Context Tag from the received packet that triggered the R1bis.
  • Responder Nonce: a 32-bit unsigned integer picked by the responder, which the initiator returns in the I2bis message.

The option defined for this message is ๐Ÿ‘‘:

  • Responder Validator: a variable-length option. It's typically a hash the responder generates, and the responder uses it together with the Responder Nonce value to verify that an I2bis message really is a reply to this R1bis.

Future extensions might add more options here too ๐Ÿฆ‹. The C-bit in the option format decides how an implementation handles a new option. See Section 5.15.


5.9. I2bis Message Format

The I2bis message is the third message in the context-recovery exchange ๐Ÿ’œ. It's sent in response to an R1bis message, after checking that the R1bis refers to an existing context, etc.

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       59      |  Hdr Ext Len  |0|  Type = 6  |   Reserved1 |0|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |R|                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                  Initiator Context Tag                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Initiator Nonce                            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Responder Nonce                            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                       Reserved2                               |
    |                                 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                 |                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                     Packet Context Tag                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                         Options                               +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The field lowdown โœจ:

  • Next Header: it's NO_NXT_HDR (59).
  • Hdr Ext Len: at least 3, since the header is 32 octets when there are no options.
  • Type: 6.
  • Reserved1: a 7-bit field reserved for future use. Set it to zero when you send it. It MUST be ignored on receipt.
  • R: a 1-bit field reserved for future use. Set it to zero when you send it. It MUST be ignored on receipt.
  • Initiator Context Tag: a 47-bit field, the Context Tag the initiator allocated for the context.
  • Initiator Nonce: a 32-bit unsigned integer picked at random by the initiator, which the responder returns in the R2 message.
  • Responder Nonce: a 32-bit unsigned integer copied from the R1bis message.
  • Reserved2: a 49-bit field reserved for future use ๐Ÿซถ. Set it to zero when you send it. It MUST be ignored on receipt. (Note that 17 bits are not sufficient, since the options need to start on a multiple-of-8-octet boundary.)
  • Packet Context Tag: a 47-bit unsigned integer, copied from the Packet Context Tag field in the received R1bis.

Here are the options defined for this message ๐Ÿ”ฅ:

  • Responder Validator: a variable-length option. It's just a copy of the Responder Validator option from the R1bis message.
  • ULID pair: when the IPv6 source and destination addresses in the IPv6 header don't match the ULID pair, this option MUST be included.
  • Forked Instance Identifier: when another instance of an existing context with the same ULID pair is being created, this option is included to tell the new instance apart from the existing one ๐Ÿ‘ฏ.
  • Locator List: optionally sent when the initiator wants to tell the responder its list of locators right away. When it's sent, the necessary HBA/CGA information for verifying the locator list MUST also be included.
  • Locator Preferences: optionally sent when the locators don't all have equal preference.
  • CGA Parameter Data Structure: included when the locator list is included, so the receiver can verify that list.
  • CGA Signature: included when some of the locators in the list use CGA (and not HBA) for verification.

Future protocol extensions might define additional options for this message ๐ŸŒธ. The C-bit in the option format defines how such a new option will be handled by an implementation. See Section 5.15.

5.10. Update Request Message Format โœจ

okay bestie, the Update Request is how a host says "hey, my locators changed!" ๐Ÿฆ‹ It can update the locator list, the locator preferences, or both ๐Ÿ’… If the list is changing, the message also carries the options needed for HBA/CGA to lock it down ๐Ÿ” The main thing that stops off-path attackers from sending fake updates is the Context Tag in the message ๐Ÿ›ก๏ธ

Here's the lowkey important bit: the Locator List and Locator Preferences options each replace whatever came before, completely ๐Ÿ’€ There's no delta system, so you can't just send the changes. You always send the whole list again ๐Ÿ˜ญ

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       59      |  Hdr Ext Len  |0|  Type = 64  |   Reserved1 |0|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |R|                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                   Receiver Context Tag                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Request Nonce                              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                         Options                               +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Here's the field breakdown ๐Ÿ“

  • Next Header: set to NO_NXT_HDR (59) ๐Ÿ™Œ
  • Hdr Ext Len: at least 1, since the header is 16 octets when there are no options ๐Ÿ“
  • Type: 64 ๐ŸŽ€
  • Reserved1: a 7-bit field reserved for future use. It's zero on transmit, and it MUST be ignored on receipt ๐ŸŒธ
  • R: a 1-bit field, also reserved for future use. It's zero on transmit, and it MUST be ignored on receipt ๐Ÿซถ
  • Receiver Context Tag: a 47-bit field holding the Context Tag the receiver allocated for the context ๐Ÿ”‘
  • Request Nonce: a 32-bit unsigned integer, a random number picked by the initiator. The peer returns it in the Update Acknowledgement message ๐ŸŽฒ

These options are defined for this message โœจ

  • Locator List: the sender's (new) locators. The locators might be unchanged and only the preferences changed ๐Ÿ“
  • Locator Preferences: sent optionally, when the locators don't all have equal preference โญ
  • CGA Parameter Data Structure (PDS): included when the locator list is included and the PDS wasn't already sent in the I2/ I2bis/R2 messages, so the receiver can verify the locator list ๐Ÿ”
  • CGA Signature: included when some of the locators in the list use CGA (and not HBA) for verification โœ๏ธ

Future protocol extensions might define more options for this message ๐Ÿ”ฎ The C-bit in the option format decides how a new option gets handled by an implementation, so check out Section 5.15 ๐Ÿฆ‹


5.11. Update Acknowledgement Message Format ๐Ÿ’Œ

This message is the reply to an Update Request ๐Ÿ’– It means the Update Request was received, and any new locators in it can now be used as source locators for packets โœ… But it does NOT mean those new locators have been verified as destinations ๐Ÿ™…โ€โ™€๏ธ The host might wait to verify a locator until it actually needs to use it as a destination, so it's chill if that's not done yet ๐Ÿซ 

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       59      |  Hdr Ext Len  |0|  Type = 65  |   Reserved1 |0|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |R|                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             |
    |                   Receiver Context Tag                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      Request Nonce                            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                         Options                               +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The fields ๐Ÿง

  • Next Header: NO_NXT_HDR (59) ๐Ÿ™Œ
  • Hdr Ext Len: at least 1, since the header is 16 octets when there are no options ๐Ÿ“
  • Type: 65 ๐ŸŽ€
  • Reserved1: a 7-bit field reserved for future use. It's zero on transmit, and it MUST be ignored on receipt ๐ŸŒธ
  • R: a 1-bit field reserved for future use. It's zero on transmit, and it MUST be ignored on receipt ๐Ÿซถ
  • Receiver Context Tag: a 47-bit field, the Context Tag the receiver allocated for the context ๐Ÿ”‘
  • Request Nonce: a 32-bit unsigned integer, copied from the Update Request message ๐Ÿ“‹

No options are currently defined for this message ๐Ÿคทโ€โ™€๏ธ Future protocol extensions might add some, and the C-bit in the option format defines how a new one gets handled by an implementation. See Section 5.15 ๐Ÿฆ‹


5.12. Keepalive Message Format ๐ŸŒˆ

This message format is defined in [4] ๐Ÿ“–

The point of this message is to make sure that when a peer is sending ULP packets on a context, it always gets some packets back in the reverse direction ๐Ÿ” If the ULP is already sending bidirectional traffic, you don't need to add extra packets ๐Ÿ™Œ But for unidirectional ULP traffic, the shim sends back some Keepalive messages whenever it's receiving ULP packets ๐Ÿ’œ


5.13. Probe Message Format ๐Ÿ”

This message and its semantics are defined in [4] ๐Ÿ“–

The goal here is to test whether locator pairs work in general ๐Ÿงช It's especially for the tricky case where one locator pair works from A to B, a different pair works from B to A, and there's no single pair that works in both directions ๐Ÿ˜ตโ€๐Ÿ’ซ The way it works is that while A sends Probe messages to B, B notices which locator pairs it has received and reports them back to A in the Probe messages it sends ๐Ÿ’…


5.14. Error Message Format ๐Ÿšจ

The Error message is generated by a Shim6 receiver when it gets a Shim6 message with critical information it can't process properly ๐Ÿ’€

If a Shim6 node receives a Shim6 packet containing information that's critical to the Shim6 protocol and the receiver doesn't support it, it sends an Error message back to whoever originated the Shim6 message ๐Ÿซ  The Error message is unacknowledged, so nobody replies to it ๐Ÿค

Heads up! Error messages can also help you debug Shim6 implementations ๐Ÿ› A range of Error Code types is reserved for exactly that purpose. Implementations may generate Shim6 Error messages with Code types in that range, instead of silently discarding Shim6 packets while you're debugging ๐Ÿ™ˆ
     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       59      |  Hdr Ext Len  |0|  Type = 68  |  Error Code |0|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |            Checksum           |            Pointer            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                         Packet in error                       +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The fields ๐Ÿ’–

  • Next Header: NO_NXT_HDR (59) ๐Ÿ™Œ
  • Hdr Ext Len: at least 1, since the header is 16 octets. It depends on the specific Error Data ๐Ÿ“
  • Type: 68 ๐ŸŽ€
  • Error Code: a 7-bit field describing the error that generated the Error message. See the Error Code list below ๐Ÿงพ
  • Pointer: a 16-bit field. It identifies the octet offset within the invoking packet where the error was detected ๐Ÿ“
  • Packet in error: as much of the invoking packet as possible, without the Error message packet going over the minimum IPv6 MTU ๐Ÿ“ฆ

The following Error Codes are defined ๐Ÿ‘‘

   +---------+---------------------------------------------------------+
   |   Code  |                       Description                       |
   |  Value  |                                                         |
   +---------+---------------------------------------------------------+
   |    0    |                Unknown Shim6 message type               |
   |    1    |              Critical option not recognized             |
   |    2    |    Locator verification method failed (Pointer to the   |
   |         |         inconsistent verification method octet)         |
   |    3    |       Locator List Generation number out of sync.       |
   |    4    | Error in the number of locators in a Locator Preference |
   |         |                          option                         |
   | 120-127 |             Reserved for debugging purposes             |
   +---------+---------------------------------------------------------+

Table 2

5.15. Option Formats โœจ

okay so the option format is basically a snapshot of the current HIP option format [20] ๐ŸŽ€ The authors are NOT planning to keep up with every change HIP makes to its option format, and they aren't reusing the same name space for option type values either. But matching the format should make it way easier to bring HIP capabilities into Shim6 as extensions if that ever becomes useful ๐Ÿฆ‹

All of the TLV parameters have a length (counting the Type and Length fields too) that's a multiple of 8 bytes ๐Ÿ’… When needed, padding MUST be added to the end of the parameter so the total length hits a multiple of 8 bytes. This keeps the data nicely aligned ๐ŸŒธ If padding is added, the Length field MUST NOT include the padding. Any padding bytes that get added MUST be zeroed by the sender, and the receiver SHOULD NOT check their values ๐Ÿซถ

So the Length field tells you the length of the Contents field, in bytes ๐Ÿ’– The total length of the TLV parameter (Type, Length, Contents, and Padding together) is related to the Length field by this formula:

Total Length = 11 + Length - (Length + 3) mod 8;

The total length of the option is the smallest multiple of 8 bytes that fits the 4 bytes of the Option header plus the option itself ๐Ÿงš You can work out the padding like this:

padding = 7 - ((Length + 3) mod 8)

And then:

Total Length = 4 + Length + padding

Here's the layout:

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |             Type            |C|             Length            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                                                               ~
 ~                          Contents                             ~
 ~                                               +-+-+-+-+-+-+-+-+
 ~                                               |    Padding    |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Here's what each field means ๐Ÿ‘‘

  • Type: a 15-bit identifier for the type of option. The options defined in this document are listed below.
  • C: the Critical bit ๐Ÿ”ฅ It's set to one if the parameter is critical and the recipient MUST recognize it. Otherwise it's zero. An implementation might treat the C-bit as part of the Type field by multiplying the type values in this specification by two.
  • Length: the length of the Contents, in bytes.
  • Contents: parameter-specific stuff, defined by the Type.
  • Padding: 0-7 bytes of padding, added if needed.

Here are the option types you'll see in this doc ๐ŸŒˆ

+------+------------------------------+
| Type |          Option Name         |
+------+------------------------------+
|   1  |      Responder Validator     |
|   2  |         Locator List         |
|   3  |      Locator Preferences     |
|   4  | CGA Parameter Data Structure |
|   5  |         CGA Signature        |
|   6  |           ULID Pair          |
|   7  |  Forked Instance Identifier  |
|  10  |   Keepalive Timeout Option   |
+------+------------------------------+

                                  Table 3

Future protocol extensions might define more options for Shim6 messages, and the C-bit is what decides how an implementation handles a brand-new option ๐Ÿ’œ

If a host gets an option it doesn't understand (one from some future extension) or one that isn't on the list of valid options for the message types above, then the Critical bit decides what happens ๐Ÿ™ˆ

  • If C=0, the option is silently ignored and the rest of the message gets processed ๐Ÿ“
  • If C=1, the host SHOULD send back a Shim6 Error message with Error Code=1, and the Pointer field points at the first octet in the Option Type field. When C=1, the rest of the message MUST NOT be processed. ๐Ÿ’€

5.15.1. Responder Validator Option Format

The responder gets to pick exactly what input goes into computing the validator, and which one-way function it uses (like MD5 or SHA1) ๐Ÿฆ‹ The only catch is that the responder has to be able to check that the validator it gets back in the I2 or I2bis message really is one that:

  1. it computed,
  2. it computed for this particular context, and
  3. isn't a replayed I2/I2bis message.

Some ideas for generating validators are in Sections 7.10.1 and 7.17.1 โœจ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 1          |0|            Length             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                           Validator                           ~
 ~                                               +-+-+-+-+-+-+-+-+
 ~                                               |    Padding    |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Validator: variable-length content, and what it means is up to the responder ๐ŸŽ€
  • Padding: 0-7 bytes of padding, added if needed. See Section 5.15.

5.15.2. Locator List Option Format

The Locator List option carries all of the sender's locators ๐ŸŒธ The order matters a LOT here, because the Locator Preferences option points at locators by their index in this list ๐Ÿ‘‘

Also, every locator goes in this option even though some of them could be built automatically from the CGA Parameter Data Structure ๐Ÿซถ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 2          |0|            Length             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                     Locator List Generation                   |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |  Num Locators |            N Octets of Verification Method    |
 +-+-+-+-+-+-+-+-+                                               |
 ~                                                               ~
 ~                                               +-+-+-+-+-+-+-+-+
 ~                                               |    Padding    |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                     Locators 1 through N                      ~
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Locator List Generation: a 32-bit unsigned integer ๐Ÿ’– It's a generation number that goes up by one for every new locator list. It makes sure the index in the Locator Preferences points at the right version of the list.
  • Num Locators: an 8-bit unsigned integer ๐Ÿ“ It's how many locators are in the option. We call this number "N" from here on.
  • Verification Method: N octets. The ith octet says which verification method applies to the ith locator ๐Ÿฆ‹
  • Padding: 0-7 bytes of padding, added if needed so the Locators start on a multiple-of-8-octet boundary. There's never any padding at the end for this option, since the Locators already add up to a multiple of 8 octets. This internal padding is counted in the Length field ๐Ÿงš
  • Locators: N 128-bit locators โœจ

The verification methods that are defined are:

+---------+----------------------------------+
|  Value  |              Method              |
+---------+----------------------------------+
|    0    |             Reserved             |
|    1    |                HBA               |
|    2    |                CGA               |
|  3-200  | Allocated using Standards action |
| 201-254 |         Experimental use         |
|   255   |             Reserved             |
+---------+----------------------------------+

                                  Table 4

5.15.3. Locator Preferences Option Format ๐ŸŽ€

Okay so this option can carry some flags that say whether a locator is known to work ๐Ÿซถ The sender can also include a notion of preferences โœจ It might make sense to define "preferences" as a combination of priority and weight, the same way DNS SRV records already have that info ๐Ÿ’… Priority gives a way to rank the locators, and within a given priority, weight gives a way to do some load sharing ๐Ÿงš See [5] for how SRV defines the interaction of priority and weight.

The bare minimum of preferences we need is being able to say a locator is "dead" ๐Ÿ’€ We can handle that with a single octet flag for each locator.

We can level that up by carrying a bigger "element" for each locator. This document currently also defines 2-octet and 3-octet elements, and we can add more info with even larger elements if we ever need to ๐ŸŒˆ

The locators are not included in the preference list ๐Ÿ™ˆ Instead, the first element refers to the locator that was in the first element in the Locator List option. The generation number carried in this option and in the Locator List option is used to verify that they refer to the same version of the locator list ๐Ÿ”ฅ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 3          |0|            Length             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                     Locator List Generation                   |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |  Element Len  |  Element[1]   |  Element[2]   |  Element[3]   |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                              ...                              ~
 ~                                               +-+-+-+-+-+-+-+-+
 ~                                               |    Padding    |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Case of Element Len = 1 is depicted.

Fields:

  • Locator List Generation: 32-bit unsigned integer. Indicates a generation number for the locator list to which the elements should apply.
  • Element Len: 8-bit unsigned integer. The length in octets of each element. This specification defines the cases when the length is 1, 2, or 3.
  • Element[i]: A field with a number of octets defined by the Element Len field. Provides preferences for the ith locator in the Locator List option that is in use.
  • Padding: Padding, 0-7 bytes, added if needed. See Section 5.15.

When the Element length equals one, the element is just a one-octet Flags field. The currently defined flags are:

  • BROKEN: 0x01
  • TRANSIENT: 0x02

The point of the BROKEN flag is to tell the peer that a given locator is known to be not working ๐Ÿ˜ญ TRANSIENT lets us tell apart the more stable addresses from the less stable ones when Shim6 is combined with IP mobility, and when we might have more stable home locators and less stable care-of-locators ๐Ÿฆ‹

When the Element length equals two, the element is a one-octet Flags field followed by a one-octet Priority field. This Priority field has the same semantics as the Priority field in DNS SRV records ๐Ÿ’œ

When the Element length equals three, the element is a one-octet Flags field, then a one-octet Priority field, and then a one-octet Weight field. This Weight field has the same semantics as the Weight field in DNS SRV records ๐Ÿ“

This document doesn't specify the format when the Element length is more than three, except that any such formats MUST be defined so that the first three octets are the same as in the above case, that is, a one-octet Flags field followed by a one-octet Priority field, and a one-octet Weight field. ๐Ÿ‘‘

5.15.4. CGA Parameter Data Structure Option Format ๐Ÿงš

This option contains the CGA Parameter Data Structure (PDS). When HBA is used to verify the locators, the PDS contains the HBA multiprefix extension in addition to the PDS mandatory fields and other extensions unrelated to Shim6 that the PDS might have. When CGA is used to verify the locators, the host also needs to include the signature in the form of a CGA Signature option, on top of the PDS option ๐Ÿซถ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 4          |0|            Length             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                   CGA Parameter Data Structure                ~
 ~                                               +-+-+-+-+-+-+-+-+
 ~                                               |    Padding    |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • CGA Parameter Data Structure: Variable length content. Content defined in [2] and [3].
  • Padding: Padding, 0-7 bytes, added if needed. See Section 5.15.

5.15.5. CGA Signature Option Format ๐Ÿ”

When CGA is used for verification of one or more of the locators in the Locator List option, the message in question will need to contain this option ๐Ÿ’–

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 5          |0|            Length             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ~                        CGA Signature                          ~
 ~                                               +-+-+-+-+-+-+-+-+
 ~                                               |    Padding    |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • CGA Signature: A variable-length field containing a PKCS#1 v1.5 signature, constructed by using the sender's private key over the following sequence of octets:
    1. The 128-bit CGA Message Type tag [CGA] value for Shim6: 0x4A 30 5662 4858 574B 3655 416F 506A 6D48. (The tag value has been generated randomly by the editor of this specification.).
    2. The Locator List Generation number of the correspondent Locator List option.
    3. The subset of locators included in the correspondent Locator List option whose verification method is set to CGA. The locators MUST be included in the order in which they are listed in the Locator List Option.
  • Padding: Padding, 0-7 bytes, added if needed. See Section 5.15.

5.15.6. ULID Pair Option Format ๐ŸŒธ

I1, I2, and I2bis messages MUST contain the ULID pair, and normally that lives in the IPv6 Source and Destination fields ๐Ÿ™Œ If the ULID for the context is different from the address pair in the Source and Destination Address fields of the IPv6 packet carrying the I1/I2/I2bis message, then the ULID Pair option MUST be included in the I1/I2/I2bis message ๐Ÿซถ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 6          |0|        Length = 36            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                       Reserved2                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 +                         Sender ULID                           +
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 +                        Receiver ULID                          +
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Reserved2: 32-bit field. Reserved for future use. Zero on transmit. MUST be ignored on receipt. (Needed to make the ULIDs start on a multiple-of-8-octet boundary.)
  • Sender ULID: A 128-bit IPv6 address.
  • Receiver ULID: A 128-bit IPv6 address.

5.15.7. Forked Instance Identifier Option Format ๐Ÿงฉ

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Type = 7          |0|         Length = 4            |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                  Forked Instance Identifier                   |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields:

  • Forked Instance Identifier: 32-bit field containing the identifier of the particular forked instance.

5.15.8. Keepalive Timeout Option Format โฐ

This option is defined in [4].


6. Conceptual Model of a Host ๐Ÿ 

This section describes a conceptual model of one possible data structure organization that hosts will maintain for the purposes of Shim6. The described organization is provided to facilitate the explanation of how the Shim6 protocol should behave. This document does not mandate that implementations adhere to this model as long as their external behavior is consistent with that described in this document. ๐Ÿ’…

6.1. Conceptual Data Structures ๐Ÿ’–

okay so the star of the whole Shim6 show is the ULID-pair context ๐ŸŽ€. It's a data structure that holds all of this info:

  • The state of the context. See Section 6.2.
  • The peer ULID: ULID(peer).
  • The local ULID: ULID(local).
  • The Forked Instance Identifier: FII. This is zero for the default context, i.e., when there is no forking.
  • The list of peer locators with their preferences: Ls(peer).
  • The generation number for the most recently received, verified peer locator list.
  • For each peer locator, the verification method to use (from the Locator List option).
  • For each peer locator, a flag specifying whether it has been verified using HBA or CGA, and a bit specifying whether the locator has been probed to verify that the ULID is present at that location.
  • The current peer locator is the locator used as the destination address when sending packets: Lp(peer).
  • The set of local locators and the preferences: Ls(local).
  • The generation number for the most recently sent Locator List option.
  • The current local locator is the locator used as the source address when sending packets: Lp(local).
  • The Context Tag used to transmit control messages and Shim6 Payload Extension headers, allocated by the peer: CT(peer).
  • The context to expect in received control messages and Shim6 Payload Extension headers, allocated by the local host: CT(local).
  • Timers for retransmission of the messages during context-establishment and update messages.
  • Depending on how an implementation determines whether a context is still in use, there might be a need to track the last time a packet was sent or received using the context.
  • Reachability state for the locator pairs as specified in [4].
  • During pair exploration, information about the Probe messages that have been sent and received as specified in [4].
  • During the context-establishment phase, the Initiator Nonce, Responder Nonce, Responder Validator, and timers related to the different packets sent (I1, I2, R2), as described in Section 7.

6.2. Context STATES ๐Ÿฆ‹

Here are the STATES that describe the Shim6 protocol. Ready? ๐Ÿ™ˆ

+---------------------+---------------------------------------------+
| STATE               | Explanation                                 |
+---------------------+---------------------------------------------+
| IDLE                | State machine start                         |
|                     |                                             |
| I1-SENT             | Initiating context-establishment exchange   |
|                     |                                             |
| I2-SENT             | Waiting to complete context-establishment   |
|                     | exchange                                    |
|                     |                                             |
| I2BIS-SENT          | Potential context loss detected             |
|                     |                                             |
| ESTABLISHED         | SHIM context established                    |
|                     |                                             |
| E-FAILED            | Context-establishment exchange failed       |
|                     |                                             |
| NO-SUPPORT          | ICMP Unrecognized Next Header type          |
|                     | (type 4, code 1) received, indicating       |
|                     | that Shim6 is not supported                 |
+---------------------+---------------------------------------------+

In addition, in each of the STATES above, some state information gets stored too. Lots of details, bestie, so stay with me ๐Ÿงš

+---------------------+---------------------------------------------+
| STATE               | Information                                 |
+---------------------+---------------------------------------------+
| IDLE                | None                                        |
|                     |                                             |
| I1-SENT             | ULID(peer), ULID(local), [FII], CT(local),  |
|                     | INIT Nonce, Lp(local), Lp(peer), Ls(local)  |
|                     |                                             |
| I2-SENT             | ULID(peer), ULID(local), [FII], CT(local),  |
|                     | INIT Nonce, RESP Nonce, Lp(local), Lp(peer),|
|                     | Ls(local), Responder Validator              |
|                     |                                             |
| ESTABLISHED         | ULID(peer), ULID(local), [FII], CT(local),  |
|                     | CT(peer), Lp(local), Lp(peer), Ls(local),   |
|                     | Ls(peer), INIT Nonce?(to receive late R2)   |
|                     |                                             |
| I2BIS-SENT          | ULID(peer), ULID(local), [FII], CT(local),  |
|                     | CT(peer), Lp(local), Lp(peer), Ls(local),   |
|                     | Ls(peer), CT(R1bis), RESP Nonce,            |
|                     | INIT Nonce, Responder Validator             |
|                     |                                             |
| E-FAILED            | ULID(peer), ULID(local)                     |
|                     |                                             |
| NO-SUPPORT          | ULID(peer), ULID(local)                     |
+---------------------+---------------------------------------------+

7. Establishing ULID-Pair Contexts โœจ

ULID-pair contexts get set up with a 4-way exchange ๐Ÿค. The best part is that it lets the responder avoid creating state on the first packet ๐Ÿ‘‘. As part of this exchange, each end allocates a Context Tag and shares that tag and its set of locators with the peer.

Sometimes the 4-way exchange isn't needed. For instance, when both ends try to set up the context at the same time, or when recovering from a context that got garbage collected or lost at one of the hosts ๐Ÿ’€.

7.1. Uniqueness of Context Tags

Every time a new context gets established, each host has to assign a unique Context Tag ๐Ÿท๏ธ. The Shim6 Payload Extension headers get demultiplexed based only on the Context Tag value (no locators involved), so the Context Tag MUST be unique for each context.

It's super important that Context Tags are hard to guess for off-path attackers ๐Ÿ˜ค. So, if an implementation uses structure in the Context Tag to make lookups faster, at least 30 bits of the Context Tag MUST be unstructured and populated by random or pseudo-random bits.

Also, to minimize the reuse of Context Tags, the host SHOULD randomly cycle through the unstructured tag name space that is reserved for randomly assigned Context Tag values (e.g., following the guidelines described in [13]).

7.2. Locator Verification

The peer's locators might need to be verified during context establishment, and also when handling locator updates in Section 10 ๐Ÿ”.

There are two separate aspects of locator verification. The first is verifying that the locator is tied to the ULID, i.e., that the host that "owns" the ULID is also the one claiming the locator "ownership". The Shim6 protocol uses the HBA or CGA techniques for this. The second is verifying that the host is actually reachable at the claimed locator. This matters not only so communication can proceed, but also to prevent 3rd party flooding attacks [15] ๐Ÿšจ. These two aspects happen at different times: the first might need to be done before packets can be received by the peer with the source locator in question, while the latter is only needed before packets are sent to the locator.

Before a host can use a locator (different than the ULID) as the source locator, it must know that the peer will accept packets with that source locator as part of this context. So the HBA/CGA verification SHOULD be performed by the host before it acknowledges the new locator by sending either an Update Acknowledgement message or an R2 message.

Before a host can use a locator (different than the ULID) as the destination locator, it MUST perform the HBA/CGA verification if this was not performed upon reception of the locator set. In addition, it MUST verify that the ULID is indeed present at that locator. This verification is performed by doing a return-routability test as part of the Probe sub-protocol [4] ๐Ÿงช.

If the verification method in the Locator List option is not supported by the host, or if the verification method is not consistent with the CGA Parameter Data Structure (e.g., the Parameter Data Structure doesn't contain the multiprefix extension and the verification method says to use HBA), then the host MUST ignore the Locator List and the message in which it is contained. The host SHOULD generate a Shim6 Error message with Error Code=2 and with the Pointer referencing the octet in the verification method that was found inconsistent ๐Ÿ™…โ€โ™€๏ธ.

7.3. Normal Context Establishment

Normal context establishment is a 4-message exchange in the order of I1, R1, I2, R2, as you can see in Figure 3 ๐Ÿ“ˆ.

      Initiator                          Responder

       IDLE                               IDLE
            ------------- I1 -------------->
       I1-SENT
            <------------ R1 ---------------
                                          IDLE
            ------------- I2 -------------->
       I2-SENT
            <------------ R2 ---------------
       ESTABLISHED                        ESTABLISHED

               Figure 3: Normal Context Establishment

7.4. Concurrent Context Establishment โœจ

okay so what if BOTH ends try to start a context for the same ULID pair at the exact same time ๐Ÿ˜ญ then you get crossing I1 messages, which is giving chaos. And since no state gets created when you receive an I1, a host can also send an I1 after it already sent an R1. iconic behavior, honestly ๐Ÿ’…

Here's the slay part: since a host remembers that it already sent an I1, it can answer an I1 from its peer (for the same ULID pair) with an R2. That gives you the exchange in Figure 4. This is needed so the host can correctly respond to retransmitted I1 messages, which happen when the R2 message got lost ๐Ÿซถ

      Host A                             Host B

       IDLE                               IDLE
            -\
       I1-SENT---\
                  ---\                  /---
                      --- I1 ---\   /---  I1-SENT
                                 ---\
                     /--- I1 ---/    ---\
                /---                     -->
            <---

            -\
       I1-SENT---\
                  ---\                  /---
                      --- R2 ---\   /---  I1-SENT
                                 ---\
                     /--- R2 ---/    ---\
                /---                     -->
            <---                          ESTABLISHED
       ESTABLISHED

                   Figure 4: Crossing I1 Messages

If a host has received an I1 and sent an R1, it has no state to remember this ๐Ÿ™ˆ So if the ULP on the host sends down packets, that might trigger the host to send an I1 message itself. Which means that while one end is sending an I1, the other is sending an I2, as you can see in Figure 5 ๐ŸŽ€

      Host A                             Host B

       IDLE                               IDLE
            -\
              ---\
       I1-SENT    ---\
                      --- I1 ---\
                                 ---\
                                     ---\
                                         -->

                                        /---
                                    /---  IDLE
                                 ---
                     /--- R1--/
                /---
            <---

            -\
       I2-SENT---\
                  ---\                  /---
                      --- I2---\   /---   I1-SENT
                                 ---\
                     /--- I1 ---/    ---\
                /---                     -->
            <---                          ESTABLISHED

            -\
       I2-SENT---\
                  ---\                  /---
                      --- R2 ---\   /---
                                 ---\
                     /--- R2 ---/    ---\
                /---                     -->
            <---                          ESTABLISHED
       ESTABLISHED

                    Figure 5: Crossing I2 and I1

7.5. Context Recovery ๐Ÿฆ‹

okay so garbage collection can totally cause a mismatch ๐Ÿ˜ญ one end is still happily using the context state while the other end has NO state at all. The end that lost it needs to recover that state before anything can use it again, bestie.

This can happen in these cases:

  • The communication is working using the ULID pair as the locator pair, but a problem comes up and the end that kept the context state decides to probe alternate locator pairs.
  • The communication is working using a locator pair that is not the ULID pair. So the ULP packets sent from a peer that kept the context state use the Shim6 Payload Extension header.
  • The host that kept the state sends a control message (e.g., an Update Request message).

In every single one of these, the peer without state gets a shim message for a Context Tag it has no context for. Not it ๐Ÿ’€

To recover, the node without the context state sends back an R1bis message, and then the recovery finishes with an I2bis and R2 message. Check out Figure 6 โœจ

        Host A                             Host B

      Context for
      CT(peer)=X                         Discards context for
                                         CT(local)=X

       ESTABLISHED                        IDLE

            ---- payload, probe, etc. -----> No context state
                                             for CT(local)=X

            <------------ R1bis ------------
                                          IDLE

            ------------- I2bis ----------->
       I2BIS_SENT
            <------------ R2 ---------------
       ESTABLISHED                        ESTABLISHED

                 Figure 6: Context Loss at Receiver

If one end garbage collected or lost the context state, it might try to make a brand new context state (for the same ULID pair) by sending an I1 message. Then the peer (which still has the context state) replies with an R1 message, and the full 4-way exchange happens again, as you can see in Figure 7 ๐ŸŒธ

        Host A                             Host B

      Context for
      CT(peer)=X                         Discards context for
      ULIDs A1, B1                       CT(local)=X

       ESTABLISHED                        IDLE

     Finds  <------------ I1 --------------- Tries to set up
     existing                                for ULIDs A1, B1
     context,
     but CT(peer)                         I1-SENT
     doesn't match
            ------------- R1 --------------->
     Left old context
     in ESTABLISHED

            <------------ I2 ---------------
     Re-create context
     with new CT(peer)                    I2-SENT
     and Ls(peer).

       ESTABLISHED
            ------------- R2 -------------->
       ESTABLISHED                        ESTABLISHED

                  Figure 7: Context Loss at Sender

7.6. Context Confusion ๐ŸŒˆ

since each end can garbage collect the context state, you can end up with one end still holding the context and trying to use it, while the other end already dropped the state. We covered this in the recovery section. BUT, for the same reasons, when one host keeps Context Tag X as CT(peer) for ULID pair <A1, B1>, the other end might end up allocating that same Context Tag as CT(local) for a different ULID pair (e.g., <A3, B1>) between the same hosts. And here's the tea โ˜• in this case the recovery mechanisms CAN'T help, because the two ULID pairs need separate Context Tags.

This kind of "confusion" can show up in two cases (assuming A is the one that kept the state and B dropped it):

  • B decides to create a context for ULID pair <A3, B1>, allocates X as its Context Tag for this, and sends an I1 to A.
  • A decides to create a context for ULID pair <A3, B1> and starts the exchange by sending I1 to B. When B receives the I2 message, it allocates X as the Context Tag for this context.

In both cases, A can detect that B has allocated X for ULID pair <A3, B1>, even though A still has X as CT(peer) for ULID pair <A1, B1>. So A can figure out that B must have lost the context for <A1, B1> ๐Ÿ‘‘

The confusion can be detected when I2/I2bis/R2 is received. We require that those messages MUST include a sufficiently large set of locators in a Locator List option, so the peer can work out whether two contexts belong to the same host by checking if there are any common locators in Ls(peer). Locator List, big brain moment ๐Ÿง 

The old context that used the Context Tag MUST be removed, because it can no longer be used to send packets. So A would forcibly remove the context state for <A1, B1, X> so it can accept the new context for <A3, B1, X>. An implementation MAY re-create a context to replace the one that was removed, in this case for <A1, B1>. The normal I1, R1, I2, R2 establishment exchange would then pick unique Context Tags for that replacement context. This re-creation is OPTIONAL, but it might be useful when there's ULP communication using the ULID pair whose context got removed ๐Ÿ“

Note that an I1 message with a duplicate Context Tag should not cause the removal of the old context state. That operation needs to be deferred until the I2 message is received ๐Ÿซถ

7.7. Sending I1 Messages ๐Ÿงš

When the shim layer decides to set up a context for a ULID pair, it starts by allocating and initializing the context state for its end. As part of this, it assigns a random Context Tag to the context that is not being used as CT(local) by any other context . If a new API is used and the ULP requests a forked context, the Forked Instance Identifier value gets set to a non-zero value. Otherwise, the FII value is zero. Then the initiator can send an I1 message and set the context STATE to I1-SENT.

The I1 message MUST include the ULID pair, normally in the IPv6 Source and Destination fields. But if the ULID pair for the context is not used as a locator pair for the I1 message, then a ULID option MUST be included in the I1 message. Also, if a Forked Instance Identifier value is non-zero, the I1 message MUST include a Context Instance Identifier option containing the correspondent value ๐Ÿ’œ

7.8. Retransmitting I1 Messages ๐Ÿ’–

If the host doesn't receive an R1 or R2 message in response to the I1 message after I1_TIMEOUT time, then it needs to retransmit the I1 message. The retransmissions should use a retransmission timer with binary exponential backoff, so they don't create congestion issues for the network when lots of hosts are doing I1 retransmissions. Also, the actual timeout value should be randomized between 0.5 and 1.5 of the nominal value to avoid self-synchronization ๐Ÿ˜ญโœจ

If there's still no response after I1_RETRIES_MAX retransmissions, then most likely the peer doesn't implement the Shim6 protocol (or a firewall is blocking the protocol). In that case, it makes sense for the host to remember NOT to keep trying to establish a context with that ULID. However, any such negative caching should be kept for at most NO_R1_HOLDDOWN_TIME, so the host can set up a context later in case the problem was that the host wasn't reachable at all when the shim tried to establish the context ๐ŸŒธ

If the host receives an ICMP error with "Unrecognized Next Header" type (type 4, code 1) and the included packet is the I1 message it just sent, then that's a more reliable sign that the peer ULID doesn't implement Shim6. Again, in this case, the host should remember not to try again to establish a context with that ULID. Such negative caching should be kept for at most ICMP_HOLDDOWN_TIME, which should be significantly longer than the previous case ๐Ÿฆ‹

7.9. Receiving I1 Messages โœจ

bestie, rule number one: a host MUST silently discard any I1 message that fails these validity checks (on top of the ones in Section 12.3) ๐Ÿ™…โ€โ™€๏ธ

  • The Hdr Ext Len field is at least 1, which means the length is at least 16 octets.

okay so when an I1 shows up, the host pulls out the ULID pair and the Forked Instance Identifier. no ULID-pair option? then the ULID pair comes from the Source and Destination fields in the IPv6 header ๐Ÿงš. no FII option? the FII is just zero. easy peasy ๐Ÿ“

next up, the host hunts for an existing context that matches that ULID pair and FII.

if it finds nothing (the STATE is IDLE), it replies with an R1 message, as described below ๐Ÿฆ‹

if the context is in ESTABLISHED STATE, the host checks that the initiator's locator is inside Ls(peer). (this check is pointless if the I1 has no ULID-pair option, so it's skipped then ๐Ÿ’…)

if the context is ESTABLISHED but the locators aren't in the locator sets, the host replies with an R1. that wraps up the I1 processing, and the context STATE stays exactly where it was ๐ŸŒธ

if the context is ESTABLISHED and the locators are in the sets, the host compares CT(peer) for the context with the CT in the I1 message:

  • if the Context Tags match, it probably means the R2 got lost and this I1 is a retransmission ๐Ÿ”. so the host replies with an R2 carrying whatever info it has for the existing context ๐Ÿ’–
  • if the Context Tags don't match, it probably means the initiator lost its context info for this ULID pair and is trying to set up a brand-new one ๐Ÿ˜ญ. so the host replies with an R1 as described below. that finishes the I1 processing, and the context STATE is unchanged โœจ

if the context is in one of the other STATEs (I1-SENT, I2-SENT, I2BIS-SENT), we're in the concurrent context establishment situation from Section 7.4 ๐ŸฅŠ. here the host leaves CT(peer) alone and replies with an R2. I1 processing is done and the context STATE doesn't change ๐Ÿซถ


7.10. Sending R1 Messages ๐ŸŽ€

when the host needs to send an R1 in response to an I1, it copies the Initiator Nonce from the I1 into the R1, generates a Responder Nonce, and works out a Responder Validator option the way the next section suggests. no state gets created on the host for this one, periodt ๐Ÿงšโ€โ™€๏ธ (fun fact: the info used to build the R1 is either already in the I1 or is global stuff that isn't tied to the specific requested context. so the S and the Responder Nonce values are the only "global" bits ๐ŸŒ)

when the host needs to send an R2 in response to an I1, it copies the Initiator Nonce from the I1 into the R2 and otherwise follows the normal rules for forming an R2 (see Section 7.14) ๐Ÿ’œ


7.10.1. Generating the R1 Validator ๐Ÿ”

as Section 5.15.1 says, how you generate the validator is a local choice, since the same node (the responder) both makes it and checks it ๐Ÿ™Œ. BUT to get the protection that's required, the validator has to be generated by meeting the conditions from Section 5.15.1. one way to do it is to keep a single secret (S) and a running counter (C) for the Responder Nonce, where the counter ticks up at fixed time intervals. that lets the responder figure out how old a Responder Nonce is, no matter which context it's being used in โณ

when the validator goes into an R1 sent in response to a specific I1, the responder can run this procedure:

First, the responder uses the current counter C value as the Responder Nonce.

Second, it hashes the following info, concatenated, as input to the one-way function:

  • The secret S
  • That Responder Nonce
  • The Initiator Context Tag from the I1 message
  • The ULIDs from the I1 message
  • The locators from the I1 message (strictly only needed if they are different from the ULIDs)
  • The Forked Instance Identifier, if such option was included in the I1 message

Third, it takes the output of the hash function and uses it as the validator value in the R1 message ๐ŸŽ‰


7.11. Receiving R1 Messages and Sending I2 Messages ๐Ÿซง

a host MUST silently discard any R1 that fails these validity checks (on top of Section 12.3's):

  • The Hdr Ext Len field is at least 1, which means the length is at least 16 octets.

when an R1 lands, the host grabs the Initiator Nonce and the Locator Pair (the latter from the Source and Destination fields in the IPv6 header) ๐Ÿ”. then it looks for an existing context that matches the Initiator Nonce, where the locators sit inside Ls(peer) and Ls(local) respectively. if there's no match, the R1 is silently discarded ๐Ÿซฅ

if there is a match, the host checks the STATE:

  • if the STATE is I1-SENT, it sends an I2 message (details below) ๐Ÿš€
  • in any other STATE (I2-SENT, I2BIS-SENT, ESTABLISHED), the host has already sent an I2, so this R1 is probably a reply to a retransmitted I1. this R1 MUST be silently discarded ๐Ÿ™…โ€โ™€๏ธ

when the host sends an I2, it includes the Responder Validator option that was in the R1 ๐Ÿ’…. the I2 MUST include the ULID pair, normally in the IPv6 Source and Destination fields ๐ŸŒˆ. if a ULID-pair option was in the I1, it MUST be in the I2 too ๐ŸŽ€. and if the Forked Instance Identifier value for this context is non-zero, the I2 MUST contain a Forked Instance Identifier option carrying that value ๐Ÿฆ‹. the I2 also has an Initiator Nonce. it doesn't have to match the one from the previous I1, just so you know โœจ

the I2 may also carry the initiator's locator list. if it does, it must also include the CGA Parameter Data Structure. and if CGA (not HBA) is used to verify one or more of the locators in that list, the initiator must also include a CGA Signature option containing the signature ๐Ÿ”

once the I2 is sent, the STATE gets set to I2-SENT ๐Ÿ’œ


7.12. Retransmitting I2 Messages ๐Ÿ”

if the initiator doesn't get an R2 within I2_TIMEOUT after sending an I2, it MAY retransmit the I2, using binary exponential backoff and randomized timers ๐ŸŽฒ. the Responder Validator option might only be good for a limited time: the peer might reject any Responder Validator option older than VALIDATOR_MIN_LIFETIME, which helps block replay attacks ๐Ÿ›ก๏ธ.

if the initiator decides not to retransmit I2s, or it still hasn't gotten an R2 after retransmitting I2_RETRIES_MAX times, the initiator SHOULD fall back to retransmitting the I1 instead ๐Ÿ”„ (bestie, don't let it spiral ๐Ÿซถ).


7.13. Receiving I2 Messages ๐Ÿ’Œ

a host MUST silently discard any I2 that fails these validity checks (on top of Section 12.3's):

  • The Hdr Ext Len field is at least 2, which means the length is at least 24 octets.

when an I2 arrives, the host pulls out the ULID pair and the Forked Instance Identifier. no ULID-pair option? the ULID pair comes from the IPv6 Source and Destination fields. no FII option? the FII is zero ๐Ÿงš

next, the host checks that the Responder Nonce is recent (nonces no older than VALIDATOR_MIN_LIFETIME SHOULD be considered recent โฐ) and that the Responder Validator option matches the validator the host would have computed for the ULID, locators, Responder Nonce, Initiator Nonce, and FII. that's a lot of checking, but it's worth it ๐Ÿ”

if a CGA Parameter Data Structure (PDS) is in the message, the host MUST verify that the actual PDS in the message matches ULID(peer) ๐Ÿชช

if any of those checks fail, the host silently discards the message, and that's the end of I2 processing for it ๐Ÿซฅ

if they all pass, the host goes looking for a context state for the initiator. it searches for a context with the extracted ULID pair and FII. if none exists, the STATE of that (non-existent) context is treated as IDLE, so the actions depend on the STATE like this:

  • if the STATE is IDLE (meaning the context doesn't exist), the host allocates a Context Tag (CT(local)), creates the context state, and sets its STATE to ESTABLISHED ๐Ÿ—๏ธ. it records CT(peer) and the peer's locator set, plus its own locator set, in the context. at this point it SHOULD do the HBA/CGA verification of the peer's locator set, as described in Section 7.2 ๐Ÿ”. then the host sends an R2 back, as described below ๐Ÿ’–
  • if the STATE is I1-SENT, the host checks whether the source locator is in Ls(peer) or in the Locator List inside the I2, AND whether the HBA/CGA verification for that specific locator passes.
    • if that's not the case, the message is silently discarded and the context STATE stays the same ๐Ÿ™ƒ
    • if it is the case, the host updates the context information (CT(peer), Ls(peer)) with the data from the I2, and the host MUST send an R2 back, as described below ๐Ÿ“จ. before it updates Ls(peer), the host SHOULD do the HBA/CGA validation of the peer's locator set, as described in Section 7.2 โœ…. then it moves to ESTABLISHED STATE ๐ŸŽ‰
  • if the STATE is ESTABLISHED, I2-SENT, or I2BIS-SENT, the host checks whether the source locator is in Ls(peer) or in the Locator List inside the I2, AND whether the HBA/CGA verification for that specific locator passes.
    • if that's not the case, the message is silently discarded and the context STATE stays the same ๐Ÿซ 
    • if it is the case, the host updates the context information (CT(peer), Ls(peer)) with the data from the I2, and the host MUST send an R2 back, as described in Section 7.14 ๐Ÿ’…. before it updates Ls(peer), the host SHOULD do the HBA/CGA validation of the peer's locator set, as described in Section 7.2 ๐Ÿ”. the context STATE doesn't change โœจ

7.14. Sending R2 Messages โœจ

okay bestie, before the host sends an R2 message ๐Ÿ’… it MUST check for a possible context confusion. that's where it could end up with multiple contexts using the same CT(peer) for the same peer host. see Section 7.15 ๐Ÿซถ

when the host needs to send an R2 message, it builds the message and its Context Tag, and copies the Initiator Nonce from whatever triggered it (I2, I2bis, or I1) ๐ŸŽ€. it may also include alternative locators and any necessary options so the peer can verify them. like, the R2 message can carry the responder's locator list and the PDS option. and if CGA (and not HBA) is used to verify the locator list, the responder also signs the key parts of the message and adds a CGA Signature option with the signature inside ๐Ÿ”.

R2 messages are never retransmitted ๐Ÿ™…โ€โ™€๏ธ. if an R2 gets lost, the initiator just resends its I2/I2bis or I1. either one makes the responder find the context state and send a fresh R2, so it all works out ๐Ÿฆ‹.


7.15. Match for Context Confusion ๐Ÿ”

this one is giving detective era. when the host receives an I2, I2bis, or R2, it MUST look for a possible context confusion, aka where it would end up with multiple contexts using the same CT(peer) for the same peer host. this can happen because those messages create a brand new context with a brand new CT(peer). the same issue applies when CT(peer) gets updated for an existing context ๐Ÿ˜ญ.

the host takes the CT(peer) for the newly created or updated context and hunts for other contexts that:

  • are in STATE ESTABLISHED or I2BIS-SENT
  • have the same CT(peer)
  • have an Ls(peer) with at least one locator in common with the newly created or updated context

if it finds one, the host checks whether the ULID pair or the Forked Instance Identifier are different from the ones in the new context:

  • if either or both are different, the peer reused the Context Tag to make a context with a different ULID pair or FII. that's basically an sign the peer lost the original context ๐Ÿ’€. so we're in a context confusion situation, and the host MUST NOT use the old context to send any packets. it MAY just discard the old context (after all, the peer already tossed it ๐Ÿ—‘๏ธ), or it MAY try to re-establish the old context by sending a new I1 message and moving its STATE to I1-SENT. either way, once this is detected, the host MUST NOT keep two contexts with overlapping Ls(peer) locator sets and the same Context Tag in ESTABLISHED STATE, because that would cause demultiplexing problems on the peer ๐Ÿ™ˆ.
  • if both are the same, then this context is actually the one being created or updated, so there's no confusion at all ๐ŸŒธ.

7.16. Receiving R2 Messages ๐ŸŽ€

A host MUST silently discard any received R2 messages that do not satisfy all of the following validity checks, in addition to those specified in Section 12.3:

  • the Hdr Ext Len field is at least 1, i.e., the length is at least 16 octets.

okay so when an R2 comes in, the host pulls out the Initiator Nonce and the Locator Pair (the locators come from the Source and Destination fields in the IPv6 header ๐Ÿงš). then it looks for an existing context that matches that Initiator Nonce, where the locators are Lp(peer) and Lp(local), respectively. what happens next depends on the STATE:

  • if no such context is found, i.e., the STATE is IDLE, the message is silently dropped. bye ๐Ÿ‘‹.
  • if STATE is I1-SENT, I2-SENT, or I2BIS-SENT, the host does the following. if a CGA Parameter Data Structure (PDS) is included in the message, the host MUST verify that the actual PDS in the message corresponds to the ULID(peer), as specified in Section 7.2. if that verification fails, the message is silently dropped. if it succeeds, the host records the information from the R2 message in the context state: it saves the peer's locator set and CT(peer). the host SHOULD perform the HBA/CGA verification of the peer's locator set at this point in time, as specified in Section 7.2 ๐Ÿ”. then the host sets its STATE to ESTABLISHED. โœจ
  • if the STATE is ESTABLISHED, the R2 message is silently ignored, since it's likely a reply to a retransmitted I2 message ๐Ÿ™„.

before the host finishes R2 processing, it MUST look for a possible context confusion, aka where it would end up with multiple contexts using the same CT(peer) for the same peer host. see Section 7.15 ๐Ÿ’–.


7.17. Sending R1bis Messages ๐Ÿฆ‹

so when a Shim6 Payload Extension header shows up and there's no current Shim6 context at the receiver, the receiver is to respond with an R1bis message. the goal is a fast re-establishment of the lost Shim6 context ๐Ÿš‘.

also, a host is to respond with an R1bis when it gets any control message with a message type in the range 64-127. (that range excludes the context-setup messages, like I1, R1, R1bis, I2, I2bis, R2, and future extensions ๐Ÿ™ƒ). this only applies when the control message refers to a non-existent context.

we assume all the incoming packets that trigger an R1bis contain a locator pair (in the address fields of the IPv6 header) and a Context Tag ๐Ÿซถ.

when any of those packets arrive, the host replies with an R1bis that includes:

  • the Responder Nonce, which is a number picked by the responder that the initiator will return in the I2bis message ๐Ÿ”ข.
  • the Packet Context Tag, which is the Context Tag contained in the received packet that triggered the R1bis message ๐Ÿท๏ธ.
  • the Responder Validator option, with a validator computed as suggested in the next section ๐Ÿ’….

7.17.1. Generating the R1bis Validator ๐Ÿ”

one way for the responder to generate validators properly is to keep a single secret (S) and a running counter C for the Responder Nonce. the counter gets incremented in fixed periods of time. this lets the responder verify the age of a Responder Nonce, no matter which context it's being used in ๐Ÿ•ฐ๏ธ.

when the validator is generated for an R1bis message (so, sent in response to a specific control packet or a packet containing the Shim6 Payload Extension header message), the responder can follow this procedure:

First, the responder uses the counter C value as the Responder Nonce.

Second, it uses the following information, concatenated, as input to the one-way function:

  • the secret S
  • that Responder Nonce
  • the Receiver Context Tag included in the received packet
  • the locators from the received packet

Third, it uses the output of the hash function as the validator string ๐ŸŒˆ.


7.18. Receiving R1bis Messages and Sending I2bis Messages ๐Ÿ’œ

A host MUST silently discard any received R1bis messages that do not satisfy all of the following validity checks, in addition to those specified in Section 12.3:

  • the Hdr Ext Len field is at least 1, i.e., the length is at least 16 octets.

when an R1bis comes in, the host extracts the Packet Context Tag and the Locator Pair (the latter from the Source and Destination fields in the IPv6 header). then it looks for an existing context where the Packet Context Tag matches CT(peer) and the locators match Lp(peer) and Lp(local), respectively ๐Ÿ•ต๏ธโ€โ™€๏ธ.

  • if no such context is found, i.e., the STATE is IDLE, the R1bis message is silently discarded.
  • if the STATE is I1-SENT, I2-SENT, or I2BIS-SENT, the R1bis message is silently discarded.
  • if the STATE is ESTABLISHED, then we're in the case where the peer has lost the context, and the goal is to try to re-establish it ๐Ÿฅบ. for that, the host leaves CT(peer) unchanged in the context state, transitions to I2BIS-SENT STATE, and sends an I2bis message. that message includes the computed Responder Validator option, the Packet Context Tag, and the Responder Nonce that were received in the R1bis message. this I2bis message is sent using the locator pair included in the R1bis message. if that locator pair differs from the ULID pair defined for this context, then a ULID option MUST be included in the I2bis message. also, if the Forked Instance Identifier for this context is non-zero, then a Forked Instance Identifier option carrying the instance identifier value for this context MUST be included in the I2bis message ๐ŸŽ€. the I2bis message may also include a locator list. if it does, it must also include the CGA Parameter Data Structure. and if CGA (and not HBA) is used to verify one or more of the locators in that list, then the initiator must also include a CGA Signature option containing the signature ๐Ÿ”.

7.19. Retransmitting I2bis Messages ๐Ÿ”

if the initiator doesn't receive an R2 message after I2bis_TIMEOUT time has passed since sending an I2bis message, it MAY retransmit the I2bis message. it uses binary exponential backoff and randomized timers to do it โณ. heads up, the Responder Validator option might have a limited lifetime ๐Ÿ™ˆ. the peer might reject Responder Validator options that are older than VALIDATOR_MIN_LIFETIME, to avoid replay attacks ๐Ÿ›ก๏ธ.

in the case that the initiator decides not to retransmit I2bis messages, or the initiator still doesn't receive an R2 message after retransmitting I2bis messages I2bis_RETRIES_MAX times, the initiator SHOULD fall back to retransmitting the I1 message ๐Ÿ’–.

7.20. Receiving I2bis Messages and Sending R2 Messages โœจ

Okay bestie, so a host MUST silently discard any I2bis message that doesn't pass all of these checks, on top of the ones in Section 12.3 ๐Ÿ™ˆ:

  • The Hdr Ext Len field is at least 3, i.e., the length is at least 32 octets.

When an I2bis message shows up, the host grabs the ULID pair and the Forked Instance Identifier from it. If there's no ULID-pair option, the ULID pair comes from the Source and Destination fields in the IPv6 header. If there's no FII option in the message, the FII value is zero ๐Ÿ’….

Next, the host checks two things. First, the Responder Nonce has to be a recent one (nonces that are no older than VALIDATOR_MIN_LIFETIME SHOULD be considered recent). Second, the Responder Validator option has to match the validator the host would have computed for the locators, Responder Nonce, and Receiver Context Tag when it sent an R1bis message ๐Ÿง.

If a CGA Parameter Data Structure (PDS) is included in the message, the host MUST verify that the actual PDS in the message corresponds to ULID(peer) ๐Ÿ”.

If any of those checks fail, the host silently discards the message, and that's it, I2bis processing is done ๐Ÿซ .

If both checks pass, the host looks for a context state for the initiator. It searches for a context with the extracted ULID pair and FII. If none exists, the STATE of that (non-existing) context is treated as IDLE, so the actions depend on the STATE like this:

  • If the STATE is IDLE (i.e., the context does not exist), the host allocates a Context Tag (CT(local)), creates the context state, and sets its STATE to ESTABLISHED โœจ. The host SHOULD NOT use the Packet Context Tag in the I2bis message for CT(local). Instead, it should pick a new random Context Tag, just like when it processes an I2 message ๐ŸŽ€. It records CT(peer) and the peer's locator set, along with its own locator set, in the context. It SHOULD perform the HBA/CGA verification of the peer's locator set at this point, as specified in Section 7.2. Then the host sends an R2 message back as specified in Section 7.14 ๐Ÿ’Œ.
  • If the STATE is I1-SENT, the host checks whether the source locator is included in Ls(peer) or in the Locator List contained in the I2bis message, and whether the HBA/CGA verification for this specific locator succeeds ๐Ÿ‘€.
    • If that isn't the case, the message is silently discarded and the context STATE stays unchanged ๐Ÿฅฒ.
    • If it is the case, the host updates the context information (CT(peer), Ls(peer)) with the data in the I2bis message, and the host MUST send an R2 message back as specified below ๐Ÿ’–. Note that before updating the Ls(peer) information, the host SHOULD perform the HBA/CGA validation of the peer's locator set at this point, as specified in Section 7.2. The host then moves to ESTABLISHED STATE ๐Ÿ‘‘.
  • If the STATE is ESTABLISHED, I2-SENT, or I2BIS-SENT, the host figures out whether at least one of these two conditions holds: i) the source locator is included in Ls(peer), or ii) the source locator is included in the Locator List contained in the I2bis message and the HBA/CGA verification for that specific locator succeeds ๐Ÿง .
    • If neither condition holds, the message is silently discarded and the context STATE stays unchanged ๐Ÿ™ƒ.
    • If at least one condition holds, the host updates the context information (CT(peer), Ls(peer)) with the data in the I2bis message, and the host MUST send an R2 message back as specified in Section 7.14 ๐Ÿซถ. Note that before updating the Ls(peer) information, the host SHOULD perform the HBA/CGA validation of the peer's locator set at this point, as specified in Section 7.2. The context STATE stays unchanged.

8. Handling ICMP Error Messages ๐Ÿ’ฅ

Okay so the routers along the path and the destination might generate ICMP error messages ๐Ÿ›ฃ๏ธ. Sometimes the Shim6 can take action and actually fix the problem that caused the error. Other times Shim6 can't solve it, and it's super important that those packets make it back up to the ULPs so they can do the right thing ๐Ÿ˜ค.

This is technically an implementation issue, since the mechanism is totally local to the host itself. But how ICMP errors get dispatched correctly to the ULP on the host matters a lot, so this section spells it out ๐Ÿ“.

All ICMP messages MUST be delivered to the ULP in all cases, except when Shim6 successfully acts on the message (for example, it picks a new path) ๐Ÿ›ค๏ธ. There SHOULD be a configuration option to unconditionally deliver all ICMP messages (including the ones Shim6 acted on) to the ULP โš™๏ธ.

Following that recommendation, these ICMP error messages should be processed by the Shim6 layer and not passed to the ULP:

ICMP error Destination Unreachable, with codes:
   0 (No route to destination)
   1 (Communication with destination administratively prohibited)
   2 (Beyond scope of source address)
   3 (Address unreachable)
   5 (Source address failed ingress/egress policy)
   6 (Reject route to destination)

ICMP Time exceeded error.

ICMP Parameter problem error, with the parameter that caused the
error being a Shim6 parameter.

These ICMP error messages report problems Shim6 can't fix, so they should be passed to the ULP (as described below) ๐Ÿ™Œ:

ICMP Packet too big error.

ICMP Destination Unreachable with Code 4 (Port unreachable).

ICMP Parameter problem (if the parameter that caused the problem
is not a Shim6 parameter).
          +--------------+
          | IPv6 Header  |
          |              |
          +--------------+
          |    ICMPv6    |
          |    Header    |
   - -    +--------------+   - -
          | IPv6 Header  |
          | src, dst as  |   Can be dispatched
  IPv6    | sent by ULP  |   unmodified to ULP
          | on host      |   ICMP error handler
  Packet  +--------------+
          |     ULP      |
  in      |    Header    |
          +--------------+
  Error   |              |
          ~     Data     ~
          |              |
   - -    +--------------+   - -

          Figure 8: ICMP Error Handling without the
                Shim6 Payload Extension Header

When the ULP packets go out without the Shim6 Payload Extension header (that is, while the initial locators=ULIDs are working), this brings no new concerns. An implementation's existing mechanism for delivering these errors to the ULP just works ๐Ÿฅฐ. Check Figure 8 ๐Ÿฆ‹.

But when the shim on the transmitting side inserts the Shim6 Payload Extension header and swaps the ULIDs in the IP address fields for some other locators, an ICMP error coming back has a "packet in error" that the ULP never actually sent ๐Ÿ˜ณ. So the implementation has to do reverse mapping on the "packet in error" before passing the ICMP error up to the ULP, including the ICMP extensions defined in [25]. Check Figure 9 โœจ.

          +--------------+
          | IPv6 Header  |
          |              |
          +--------------+
          |    ICMPv6    |
          |    Header    |
   - -    +--------------+   - -
          | IPv6 Header  |
          | src, dst as  |   Needs to be
  IPv6    | modified by  |   transformed to
          | shim on host |   have ULIDs
          +--------------+   in src, dst fields,
  Packet  |  Shim6 ext.  |   and Shim6 Ext.
          |    Header    |   header removed
  in      +--------------+   before it can be
          |  Transport   |   dispatched to the ULP
  Error   |    Header    |   ICMP error handler.
          +--------------+
          |              |
          ~     Data     ~
          |              |
   - -    +--------------+   - -

Figure 9: ICMP Error Handling with the Shim6 Payload Extension Header

This mapping is different from what happens when packets come in from the peer with Shim6 Payload Extension headers, because in that case the packets contain CT(local) ๐Ÿ”„. But ICMP errors have a "packet in error" with a Shim6 Payload Extension header containing CT(peer), since those packets were meant to be received by the peer ๐Ÿ“ฌ. Either way, the <Source Locator, Destination Locator, CT(peer)> tuple has to be unique when the peer receives it, so the local host should also only be able to find one context that matches this tuple ๐ŸŽฏ.

If the ICMP error is a "packet too big", the reported MTU must be adjusted to be 8 octets less, since the shim adds 8 octets when sending packets ๐Ÿ“.

Once the "packet in error" has had the original ULIDs put back in, the Shim6 Payload Extension header can be removed. The result is a "packet in error" that goes up to the ULP and looks like the shim never existed ๐Ÿช„.


9. Teardown of the ULID-Pair Context ๐Ÿซง

Each host can unilaterally decide when to tear down a ULID-pair context ๐Ÿ™‹. It is RECOMMENDED that hosts don't tear the context down when they know some upper-layer protocol might use it. For example, an implementation might know this if there's an open socket connected to ULID(peer). But sometimes the shim layer just doesn't have that knowledge, like with UDP apps that don't connect their sockets, or with any app that keeps higher-level state across (TCP) connections and UDP packets ๐Ÿฅบ.

So it is RECOMMENDED that implementations minimize premature teardown by watching how much traffic is sent and received using the context, and only tearing the state down once it seems quiet ๐Ÿคซ. A reasonable approach is to not tear down a context until at least 5 minutes have passed since the last message was sent or received using it. (Note that packets which use the ULID pair as a locator pair and don't need address rewriting by the Shim6 layer also count as using the associated Shim6 context ๐Ÿ’œ.)

Since there's no explicit, coordinated removal of context state, Context Tag reuse can get messy ๐ŸŒ€. One end might remove the state and reuse that Context Tag for some other communication, and then the peer might try to use the old context (which it didn't remove) ๐Ÿ˜ฌ. The protocol has mechanisms to recover from this. They work whether the state removal was total and accidental (like a crash and reboot of the host), or just a garbage collection of shim state that didn't seem to be in use ๐Ÿงน. Still, the host should try to minimize reuse of Context Tags by randomly cycling through the 2^47 Context Tag values ๐ŸŽฒ. (See Appendix C for a summary of how recovery works in the different cases ๐Ÿ“š.)


10. Updating the Peer ๐Ÿ’•

The Update Request and Acknowledgement are used for two things: updating the list of locators (which is only possible when CGA is used to verify the locator(s)), and updating the preferences associated with each locator ๐Ÿฆ„.

10.1. Sending Update Request Messages โœจ

okay so when a host's locator set changes, it can tell its bestie (the peer) by sending an Update Request ๐Ÿ’Œ. If the preferences for that locator set change, it can spill that tea to the peer too ๐Ÿ’…. The Update Request message can include just a Locator List option (to convey the new set of locators), just a Locator Preferences option, or both a new Locator List and new Locator Preferences. main character energy, you pick ๐Ÿ‘‘

If the host sends a new Locator List, it picks a new random, local generation number, records it in the context, and puts it in the Locator List option ๐ŸŽ€. Any Locator Preference option, whether it's sent in the same Update Request or a future one, uses that generation number so the preferences get applied to the correct version of the locator list. no mix-ups allowed ๐Ÿ™…โ€โ™€๏ธ

The host picks a random Request Nonce for each update and keeps the same nonce for any retransmissions of the Update Request. The nonce is how the acknowledgement gets matched back to the request ๐Ÿ”‘

The Update Request message can also include a CGA Parameter Data Structure (this is needed if the CGA PDS wasn't exchanged before). If CGA (and not HBA) is used to verify one or more of the locators in the locator list, then a CGA Signature option containing the signature must also be included in the Update Request message ๐Ÿ”

10.2. Retransmitting Update Request Messages ๐Ÿ”

If the host doesn't get an Update Acknowledgement R2 message back for its Update Request after UPDATE_TIMEOUT time, it needs to retransmit the Update Request message ๐Ÿ˜ฌ. The retransmissions should use a retransmission timer with binary exponential backoff, so lots of hosts retransmitting at once don't cause congestion chaos for the network ๐ŸŒŠ. The actual timeout value also gets randomized between 0.5 and 1.5 of the nominal value, which keeps everyone from syncing up (self-synchronization is not the vibe) โœจ

If there's no response, the retransmissions keep going forever ๐Ÿซ . The binary exponential backoff stops at MAX_UPDATE_TIMEOUT, but the only way retransmissions stop when there's no acknowledgement is when Shim6, through the REAP protocol or some other mechanism, decides to discard the context state because there's no ULP usage combined with no responses to the REAP protocol. it's giving ghosted ๐Ÿ‘ป

10.3. Newer Information while Retransmitting ๐Ÿฆ‹

There can be at most one outstanding Update Request message at any time. So until an update with a new Locator List has been acknowledged, for example, a newer Locator List or new Locator Preferences can't just be sent. BUT, when there's newer information and the older info hasn't been acknowledged yet, the host can abandon the previous update instead of waiting, and build a new Update Request (with a new Request Nonce) that includes the new information along with the info that hasn't been acknowledged yet. it's a clean restart and I love that for us ๐Ÿงน

For example, say the original locator list was just (A1, A2), and an Update Request with the Locator List (A1, A3) is still outstanding. If the host decides it should both add A4 to the locator list and mark A1 as BROKEN, then it would need to:

  • Pick a new random Request Nonce for the new Update Request.
  • Pick a new random generation number for the new locator list.
  • Form the new locator list: (A1, A3, A4).
  • Form a Locator Preference option that uses the new generation number and has the BROKEN flag for the first locator.
  • Send the Update Request and start a retransmission timer.

Any Update Acknowledgement that doesn't match the current Request Nonce (for instance, an acknowledgement for the abandoned Update Request) will be silently ignored. ignore the old stuff, periodt ๐Ÿ’…

10.4. Receiving Update Request Messages ๐Ÿ“ฌ

A host MUST silently discard any received Update Request messages that don't satisfy all of the following validity checks, in addition to those specified in Section 12.3:

  • The Hdr Ext Len field is at least 1, i.e., the length is at least 16 octets.

When an Update Request message comes in, the host pulls the Context Tag out of it. Then it looks for a context with a CT(local) that matches that Context Tag. If it can't find one, it sends an R1bis message as specified in Section 7.17 ๐Ÿซฃ

Context Tags can be reused, so the host MUST verify that the IPv6 Source Address field is part of Ls(peer) and that the IPv6 Destination Address field is part of Ls(local). If that isn't the case, the sender of the Update Request has a stale context that just happens to match the CT(local) for this context. In that case, the host MUST send an R1bis message and otherwise ignore the Update Request message. the stale context is not it ๐Ÿ™ˆ

If a CGA Parameter Data Structure (PDS) is included in the message, the host MUST verify that the actual PDS in the packet corresponds to the ULID(peer). If that verification fails, the message is silently discarded ๐Ÿ—‘๏ธ

Then, depending on the STATE of the context:

  • If ESTABLISHED, proceed to process the message.
  • If I1-SENT, discard the message and stay in I1-SENT.
  • If I2-SENT, send I2 and proceed to process the message.
  • If I2BIS-SENT, send I2bis and proceed to process the message.

The verification issues for the locators carried in the Update Request message are specified in Section 7.2. If the locator list can't be verified, this procedure should send a Shim6 Error message with Error Code=2. In any case, if it can't be verified, there's no further processing of the Update Request ๐Ÿšซ

Once any Locator List option in the Update Request has been verified, the peer generation number in the context gets updated to match the one in the Locator List option โœ…

If the Update Request message contains a Locator Preference option, the generation number in that preference option is compared with the peer generation number in the context. If they don't match, the host generates a Shim6 Error message with Error Code=3, and the Pointer field refers to the first octet in the Locator List Generation number in the Locator Preference option. Also, if the number of elements in the Locator Preference option doesn't match the number of locators in Ls(peer), a Shim6 Error message with Error Code=4 is sent, with the Pointer field referring to the first octet of the Length field in the Locator Preference option. In both failure cases, no further processing happens for the Update Request message ๐Ÿ’€

If the generation numbers match, the locator preferences get recorded in the context ๐Ÿ“

Once the Locator List option (if present) has been verified and any new locator list or locator preferences have been recorded, the host sends an Update Acknowledgement message. It copies the nonce from the request and uses the CT(peer) as the Receiver Context Tag ๐Ÿซถ

Any new locators (or, more likely, new locator preferences) might have the host wanting to pick a different locator pair for the context. For instance, that happens if the Locator Preferences option lists the current Lp(peer) as BROKEN. The host uses the reachability exploration procedure described in [4] to verify that the new locator is reachable before changing Lp(peer) ๐Ÿ”

10.5. Receiving Update Acknowledgement Messages ๐Ÿ’Œ

A host MUST silently discard any received Update Acknowledgement messages that don't satisfy all of the following validity checks, in addition to those specified in Section 12.3:

  • The Hdr Ext Len field is at least 1, i.e., the length is at least 16 octets.

When an Update Acknowledgement comes in, the host pulls out the Context Tag and the Request Nonce. Then it looks for a context with a CT(local) that matches the Context Tag. If it can't find one, it sends an R1bis message as specified in Section 7.17 ๐Ÿซ 

Since Context Tags can be reused, the host MUST verify that the IPv6 Source Address field is part of Ls(peer) and that the IPv6 Destination Address field is part of Ls(local). If that isn't the case, the sender of the Update Acknowledgement has a stale context that happens to match the CT(local) for this context. In that case, the host MUST send an R1bis message and otherwise ignore the Update Acknowledgement message. same stale-context drama as before ๐Ÿ™„

Then, depending on the STATE of the context:

  • If ESTABLISHED, proceed to process the message.
  • If I1-SENT, discard the message and stay in I1-SENT.
  • If I2-SENT, send R2 and proceed to process the message.
  • If I2BIS-SENT, send R2 and proceed to process the message.

If the Request Nonce doesn't match the nonce for the last sent Update Request for the context, the Update Acknowledgement is silently ignored. If the nonce does match, the update is complete and the Update retransmit timer can be reset โฑ๏ธโœจ

11. Sending ULP Payloads ๐Ÿš€

When there's no context state for the ULID pair on the sender, there's no effect on how ULP packets get sent. If the host uses some heuristic to decide when to do a deferred context establishment, it might need to do some accounting (counting the packets sent and received) even before there's a ULID-pair context ๐Ÿงฎ

If the context isn't in the ESTABLISHED or I2BIS-SENT STATE, there's also no effect on how ULP packets are sent. Only in the ESTABLISHED and I2BIS-SENT STATEs does the host have CT(peer) and Ls(peer) set ๐ŸŽฏ

If there's a ULID-pair context for the ULID pair, the sender needs to check whether the context uses the ULIDs as locators. That means checking whether Lp(peer) == ULID(peer) and Lp(local) == ULID(local) ๐Ÿ”Ž

If that's the case, packets can be sent unmodified by the shim ๐Ÿ’–. If it isn't the case, then the logic in Section 11.1 needs to be used.

There's also some maintenance activity relating to (un)reachability detection, whether or not packets are sent with the original locators. The details of this are out of scope for this document and are specified in [4] ๐Ÿง 

11.1. Sending ULP Payload after a Switch ๐Ÿ’…

okay so when you're sending packets and there's a ULID-pair context for the ULID pair, but that ULID pair is no longer being used as the locator pair, the sender needs to transform the packet ๐Ÿ”„. Besides swapping the IPv6 Source and Destination fields for a locator pair, an 8-octet header gets added so the receiver can find the context and undo the transformation ๐ŸŽ€.

If something failed and caused a switch, and then the context switches back to using the ULID pair as the locator pair, the sender doesn't need to transform anything anymore. So there's no need to include the 8-octet Extension header โœจ.

First, the IP address fields get replaced. The IPv6 Source Address field is set to Lp(local) and the Destination Address field is set to Lp(peer). Bestie, this MUST NOT cause any recalculation of the ULP checksums ๐Ÿ”’. The ULP checksums are carried end-to-end, and the ULP pseudo-header contains the ULIDs that are preserved end-to-end, so there's no reason to touch them.

The sender skips any "Routing Sublayer Extension headers" the ULP might have included. That means any Hop-by-Hop Extension header, any Routing header, and any Destination Options header that is followed by a Routing header. After any of those, the Shim6 Extension header gets added ๐Ÿงš. This might land before a Fragment header, a Destination Options header, an ESP or AH header, or a ULP header.

The inserted Shim6 Payload Extension header includes the peer's Context Tag. It takes on the Next Header value from the preceding Extension header, since that Extension header will have a Next Header value of Shim6 ๐Ÿ“.


12. Receiving Packets โœจ

The receive side can get packets associated with a Shim6 context, with or without the Shim6 Extension header. If the ULID pair is being used as a locator pair, the packets won't have the Shim6 Extension header, and they'll get processed by the Shim6 layer as described below ๐ŸŒธ. If the received packet does carry the Shim6 Extension header, it's normal IPv6 receive-side processing: the receiver parses the (extension) headers in order. When it finds a Shim6 Extension header, it looks at the P field. If that bit is zero, the packet must be passed to the Shim6 payload handling for rewriting. Otherwise, the packet goes to the Shim6 control handling ๐Ÿ’….

12.1. Receiving Payload without Extension Headers ๐ŸŒธ

The receiver extracts the IPv6 Source and Destination fields and uses them to find a ULID-pair context, where the IPv6 address fields match ULID(local) and ULID(peer). If a context is found, it appears not to be quiescent. This should be remembered so the context doesn't get torn down, and it's also used for reachability detection as described in [4] ๐Ÿซถ. Then the host carries on with the normal processing of the IP packet.

12.2. Receiving Shim6 Payload Extension Headers ๐Ÿฆ‹

The receiver pulls the Context Tag out of the Shim6 Payload Extension header and uses it to find a ULID-pair context. If no context is found, the receiver SHOULD generate an R1bis message (see Section 7.17) ๐Ÿ™ˆ.

Then it depends on the STATE of the context:

  • If ESTABLISHED, proceed to process message.
  • If I1-SENT, discard the message and stay in I1-SENT.
  • If I2-SENT, send I2 and proceed to process the message.
  • If I2BIS-SENT, send I2bis and proceed to process the message.

With the context in hand, the receiver can now replace the IP address fields with the ULIDs kept in the context ๐Ÿ‘‘. Finally, the Shim6 Payload Extension header is removed from the packet (so the ULP doesn't get confused by it), and the Next Header value in the preceding header is set to be the actual protocol number for the payload. Then the packet can be passed to the protocol identified by the Next Header value. That might be some function associated with the IP endpoint sublayer or a ULP.

If the host is using some heuristic for deciding when to do a deferred context establishment, the host might need to do some accounting, like counting the packets sent and received for packets that don't have a Shim6 Extension header and have no context. But whether it needs that depends on which heuristics the implementation picked ๐Ÿค“.

12.3. Receiving Shim Control Messages ๐Ÿ”

A shim control message gets its Checksum field verified. The Shim Header Length field is verified against the length of the IPv6 packet too, to make sure the shim message doesn't claim to end past the end of the IPv6 packet. Finally, it checks that neither the IPv6 Destination field nor the IPv6 Source field is a multicast address or an unspecified address. If any of those checks fail, the packet is silently dropped ๐Ÿ’€.

The message then gets dispatched based on the shim message type, and each message type is processed as described elsewhere in this document. If the packet has a shim message type that's unknown to the receiver, a Shim6 Error message with Error Code=0 is generated and sent back. The Pointer field is set to point at the first octet of the shim message type ๐Ÿšจ.

All the control messages can contain any options with C=0. If there's any option in the message with C=1 that isn't known to the host, then the host MUST send a Shim6 Error message with Error Code=1, with the Pointer field referencing the first octet of the Option Type ๐Ÿซฃ.

12.4. Context Lookup ๐Ÿ—๏ธ

We assume that each shim context has its own STATE machine. We also assume that a dispatcher delivers incoming packets to the STATE machine they belong to. Here, we describe the rules the dispatcher uses to deliver packets to the correct shim context STATE machine ๐Ÿงš.

There's one STATE machine per identified context. It's conceptually identified by the ULID pair and the Forked Instance Identifier (which is zero by default), or identified by CT(local). However, the detailed lookup rules are more complex, especially during context establishment.

Clearly, if the required context isn't established, it will be in IDLE STATE.

During context establishment, the context is identified as follows:

  • I1 packets: Deliver to the context associated with the ULID pair and the Forked Instance Identifier.
  • I2 packets: Deliver to the context associated with the ULID pair and the Forked Instance Identifier.
  • R1 packets: Deliver to the context with the locator pair included in the packet and the Initiator Nonce included in the packet (R1 does not contain a ULID pair or the CT(local)). If no context exists with this locator pair and Initiator Nonce, then silently discard.
  • R2 packets: Deliver to the context with the locator pair included in the packet and the Initiator Nonce included in the packet (R2 does not contain a ULID pair or the CT(local)). If no context exists with this locator pair and Initiator Nonce, then silently discard.
  • R1bis packets: Deliver to the context that has the locator pair and the CT(peer) equal to the Packet Context Tag included in the R1bis packet.
  • I2bis packets: Deliver to the context associated with the ULID pair and the Forked Instance Identifier.
  • Shim6 Payload Extension headers: Deliver to the context with CT(local) equal to the Receiver Context Tag included in the packet.
  • Other control messages (Update, Keepalive, Probe): Deliver to the context with CT(local) equal to the Receiver Context Tag included in the packet. Verify that the IPv6 Source Address field is part of Ls(peer) and that the IPv6 Destination Address field is part of Ls(local). If not, send an R1bis message.
  • Shim6 Error messages and ICMP errors that contain a Shim6 Payload Extension header or other shim control packet in the "packet in error": Use the "packet in error" for dispatching as follows. Deliver to the context with CT(peer) equal to the Receiver Context Tag -- Lp(local) being the IPv6 source address and Lp(peer) being the IPv6 destination address.

In addition, the shim on the sending side needs to be able to find the context state when a ULP packet is passed down from the ULP. In that case, the lookup key is the pair of ULIDs and FII=0. If we have a ULP API that allows the ULP to do context forking, then presumably the ULP would pass down the Forked Instance Identifier ๐ŸŒˆ.


13. Initial Contact ๐ŸŒˆ

The initial contact is some non-shim communication between two ULIDs, as described in Section 2. At that point in time, there's no activity in the shim ๐Ÿซถ.

Whether or not the shim ends up being used (for example, the peer might not support Shim6), it's highly desirable that the initial contact can be established even if there's a failure for one or more IP addresses ๐Ÿ’–.

The approach taken is to rely on the applications and the transport protocols to retry with different source and destination addresses. That's consistent with what's already specified in "Default Address Selection for IPv6" [7], plus some fixes to that specification [9] that make it try different source addresses and not only different destination addresses ๐Ÿ”ฅ.

The implementation of such an approach can potentially result in long timeouts. For instance, picture a naive implementation at the socket API that uses getaddrinfo() to retrieve all destination addresses, then tries to bind() and connect() to try all source and destination address combinations, and waits for TCP to time out for each combination before trying the next one ๐Ÿ˜ญ.

However, if implementations wrap this in some new connect-by-name() API and use non-blocking connect calls, it's possible to cycle through the available combinations much more rapidly until a working source and destination pair is found โญ. So the issues in this domain are issues of implementations and the current socket API, not issues of protocol specification. Honestly, providing an easy-to-use connect-by-name() API for TCP and other connection-oriented transports is easy. Providing a similar capability at the API for UDP is hard, though, because the protocol itself doesn't provide any "success" feedback. Still, even the UDP issue is one of APIs and implementation ๐ŸŽ€.


14. Protocol Constants ๐Ÿ“

The protocol uses the following constants:

I1_RETRIES_MAX = 4

I1_TIMEOUT = 4 seconds

NO_R1_HOLDDOWN_TIME = 1 min

ICMP_HOLDDOWN_TIME = 10 min

I2_TIMEOUT = 4 seconds

I2_RETRIES_MAX = 2

I2bis_TIMEOUT = 4 seconds

I2bis_RETRIES_MAX = 2

VALIDATOR_MIN_LIFETIME = 30 seconds

UPDATE_TIMEOUT = 4 seconds

MAX_UPDATE_TIMEOUT = 120 seconds

The retransmit timers (I1_TIMEOUT, I2_TIMEOUT, UPDATE_TIMEOUT) are subject to binary exponential backoff, as well as to randomization across a range of 0.5 and 1.5 times the nominal (backed off) value. This removes any risk of synchronization between lots of hosts performing independent shim operations at the same time ๐Ÿซถ.

The randomization is applied after the binary exponential backoff. So the first retransmission would happen based on a uniformly distributed random number in the range of [0.5*4, 1.5*4] seconds. The second retransmission happens [0.5*8, 1.5*8] seconds after the first one, and so on ๐Ÿงš.


15. Implications Elsewhere โœจ

15.1. Congestion Control Considerations ๐ŸŒธ

okay so when the locator pair a Shim6 context is using suddenly becomes unreachable, Shim6 diverts everything through a different locator pair ๐Ÿฆ‹ and ngl, that usually means the packets are taking a whole new network path โœจ. so it is recommended that Shim6 follows the recommendation defined in [21] and tells the upper layers about the path change ๐Ÿ’…, so their congestion control can react accordingly. that's the glow-up ๐Ÿซถ

15.2. Middle-Boxes Considerations ๐Ÿงš

okay this one is lowkey tricky ๐Ÿ‘€. data packets in a Shim6 context that carry the Shim6 Payload header have alternative locators in the Source and Destination Address fields of the IPv6 header, not the ULIDs. meanwhile, the upper layers of both peers work with the ULID pair that Shim6 hands them, not the locator pair actually sitting in the IPv6 header ๐Ÿ’œ. Shim6 doesn't modify the data packets, but since a constant ULID pair is shown upward no matter how the locators change, the relation between the upper-layer header (such as TCP, UDP, ICMP, ESP, etc) and the IPv6 header gets shifted ๐Ÿ™ˆ. specifically, when the Shim6 Extension header is present and the data packets are TCP, UDP, or ICMP, the pseudo-header used for the checksum contains the ULID pair instead of the locator pair in the packet ๐ŸŽ€.

it's possible that some firewalls or other middle-boxes will try to check the validity of upper-layer sanity checks on the fly ๐Ÿ˜ฌ. if they do that based on the actual source and destination addresses in the IPv6 header, without considering the Shim6 context information (in particular, without replacing the locator pair with the ULID pair used by the Shim6 context), those checks may fail. those middle-boxes need to be updated so they can parse the Shim6 Payload header and find the next header. it is recommended that firewalls and other middle-boxes do not drop packets carrying the Shim6 Payload header just because the upper-layer validity checks look wrong when they involve the addresses in the IPv6 header, unless they are able to determine the ULID pair of the Shim6 context associated with the data packet and use that ULID pair for the verification ๐Ÿ’–.

in the particular case of TCP, UDP, and ICMP checksums, it is recommended that firewalls and other middle-boxes do not drop TCP, UDP, and ICMP packets that carry the Shim6 Payload header with apparently incorrect checksums, when they use the addresses in the IPv6 header for the pseudo-header computation, unless they can determine the ULID pair of the Shim6 context associated with the data packet and use that ULID pair to work out the checksum that must be present in a packet with addresses rewritten by Shim6 โœจ.

firewalls that today pass limited traffic, e.g., outbound TCP connections, would presumably block the Shim6 protocol ๐Ÿšซ. this means that even when Shim6-capable hosts are talking, the I1 messages would be dropped, so the hosts would never find out their peer is Shim6-capable. ngl this is actually a benefit ๐ŸŒˆ, because if the hosts managed to set up a ULID-pair context, the firewall would probably drop the "different" packets sent after a failure (the ones using the Shim6 Payload Extension header with a TCP packet inside). so stateful firewalls that are modified to pass Shim6 messages should also be modified to pass the Shim6 Payload Extension header, so the shim can use the alternate locators to recover from failures ๐Ÿ›Ÿ. this presumably means the firewall needs to track the set of locators in use by looking at the Shim6 control exchanges. such firewalls might even want to verify the locators using the HBA/CGA verification themselves, and they can do that without modifying any of the Shim6 packets passing through them ๐Ÿ‘‘.

15.3. Operation and Management Considerations ๐Ÿ“

this section looks at some aspects of operating and managing the Shim6 protocol ๐Ÿ› ๏ธ.

Deployment of the Shim6 protocol: Shim6 is a host-based solution ๐Ÿ’ป. so to deploy it, the stacks of the hosts using Shim6 need to be updated to support it. this makes the rollout incremental, because there's no flag day, just single host updates ๐Ÿฅณ. if Shim6 gets deployed in a site, the hosts can be updated gradually. only end hosts need updating, and no router changes are required ๐Ÿ™Œ. however, to actually benefit from Shim6, both ends of a communication should support it, meaning both hosts must be updated to use it. nevertheless, Shim6 has a deferred context-setup capability, so end hosts can set up normal IPv6 communications first and then, later on, if both endpoints are Shim6-capable, set up the Shim6 context ๐Ÿฆ‹. this is a huge deployment win, since Shim6-enabled nodes can talk perfectly fine with non-Shim6-capable nodes without causing any problems ๐Ÿ’….

Configuration of Shim6-capable nodes: Shim6 doesn't need any specific configuration to provide its basic features โญ. it's designed to give upper layers a default service that should satisfy general applications. the Shim6 layer will automatically try to protect long-lived communications by triggering the setup of a Shim6 context, using some predefined heuristics ๐Ÿง . if some applications need special tuning, that may need extra configuration ๐ŸŽ›๏ธ. similar considerations apply to a site that's trying to do some traffic engineering by using different preferences for different locators ๐Ÿ—บ๏ธ.

Address and prefix configuration: Shim6 assumes that a multihomed site will have multiple prefixes available ๐Ÿ˜๏ธ. that configuration can add to the operational work on a network ๐Ÿ˜ฎโ€๐Ÿ’จ. however, having multiple prefixes in a site and multiple addresses on one interface is an IPv6 capability that goes way beyond Shim6, and it's expected to be widely used ๐ŸŒ. so even though this is the case for Shim6, the implications of that configuration are beyond Shim6 and must be addressed for the generic IPv6 case ๐Ÿ’œ. still, Shim6 also assumes Shim6 hosts use CGA/HBA addresses. this means Shim6-capable hosts should configure their addresses using HBA/CGA generation mechanisms ๐Ÿ”. more on this can be found at [19] ๐Ÿ“–.

15.4. Other Considerations ๐ŸŽ€

the general Shim6 approach, and the specifics of this proposed solution, have implications elsewhere, including:

  • Applications that perform referrals or callbacks using IP addresses as the 'identifiers' can still function in limited ways, as described in [18]. but for those applications to take advantage of multiple locators for redundancy, they need to be modified to either use Fully Qualified Domain Names as the 'identifiers', or pass all the locators as the 'identifiers'. in other words, the 'identifier' from the application's perspective becomes a set of IP addresses instead of a single IP address ๐Ÿงšโ€โ™€๏ธ.
  • Signaling protocols for QoS, or for other things that involve having devices in the network path look at IP addresses and port numbers (or at IP addresses and Flow Labels), need to be invoked on the hosts when the locator pair changes due to a failure ๐Ÿšจ. at that point, those protocols need to tell the devices that a new pair of IP addresses will be used for the flow. note that this is the case even though this protocol, unlike some earlier proposals, does not overload the Flow Label as a Context Tag. the in-path devices need to know about the new locators even though the Flow Label stays the same ๐Ÿท๏ธ.
  • MTU implications. By computing a minimum over the recently observed path MTUs, the path MTU mechanisms we use are robust against different packets taking different paths through the Internet ๐ŸŒ. when Shim6 fails over from one locator pair to another, packets might travel over a different path through the Internet, so the path MTU might be quite different ๐Ÿ“. to deal with that MTU change, the usage of Packetization Layer Path MTU Discovery as defined in [24] is recommended ๐Ÿ”.

the fact that the shim will add an 8-octet Shim6 Payload Extension header to the ULP packets after a locator switch can also affect the usable path MTU for the ULPs ๐Ÿซง. in this case the MTU change is local to the sending host, so conveying the change to the ULPs is an implementation matter. by conveying the information to the transport layer, it can adapt and reduce the Maximum Segment Size (MSS) accordingly ๐Ÿฅฐ.

16. Security Considerations ๐Ÿ”โœจ

okay bestie, this section is where the spec checks how it handles all the scary stuff ๐Ÿ˜ญ and it's SO thorough. it starts by saying it meets the concerns in [15] one by one, and then it goes through them like a checklist ๐Ÿ’…

  • the HBA [3] and CGA [2] techniques are used to verify the locators so an attacker can't redirect the packet stream somewhere else. that handles the threats in Sections 4.1.1, 4.1.2, 4.1.3, and 4.2 of [15] ๐Ÿ›ก๏ธ they give similar protection but have different functionality and different computational costs, so it's not one-size-fits-all

The HBA mechanism is all about generating every address of a multihomed host as an unalterable set of intrinsically bound IPv6 addresses, called an HBA set ๐Ÿ’œ the addresses bake a cryptographic one-way hash of the prefix set into the interface identifier part. so the binding between all the available addresses is literally encoded inside the addresses, which gives you hijacking protection. any peer using the shim protocol node can check, with a simple hash calculation, that the alternative addresses offered to continue the communication are bound to the initial address. efficient AND secure, it's giving ๐Ÿ”ฅ

In a CGA-based approach, the address used as the ULID is a CGA that contains a hash of a public key in its interface identifier ๐Ÿ”‘ that makes a secure binding between the ULID and its key pair. each peer can then use the matching private key to sign the shim messages that carry locator set info. the trust chain goes like this: the ULID is securely bound to the key pair because it holds the hash of the public key, and the locator set is bound to that public key through the signature. chef's kiss ๐Ÿ‘Œ

Either HBA or CGA gives you time-shifted attack protection (see Section 4.1.2 of [15]), since the ULID is securely bound to a locator set that only the owner of the ULID can define ๐Ÿฆ‹ and heads up, the minimum acceptable key length for RSA keys used to generate CGAs MUST be at least 1024 bits. any implementation should follow prudent cryptographic practice when picking key lengths too ๐Ÿซถ

  • 3rd party flooding attacks (Section 4.3 of [15]) are blocked by requiring a Shim6 peer to complete a successful Reachability probe + reply exchange before it accepts a new locator as a packet destination ๐ŸŒธ no random new addresses getting in without a handshake, periodt
  • the first message doesn't create any state on the responder ๐Ÿงš there's a 3-way exchange required before the responder creates any state at all. so a state-based DoS attack (where someone tries to eat all the memory on the responder) at least makes the attacker create state and use up their own resources. it also gives you an IPv6 address the attacker was using, which is so useful ๐Ÿ™ˆ
  • the context-establishment messages use nonces to stop replay attacks (Section 4.1.4 of [15]) and to stop off-path attackers from messing with the establishment ๐ŸŽ€
  • every control message of the Shim6 protocol past context establishment carries the Context Tag assigned to that particular context ๐Ÿ’– so an attacker has to find out that Context Tag before they can spoof any Shim6 control message (Section 4.4 of [15]). finding it probably means the attacker has to be on the path to sniff the value. so this technique protects Shim6 against off-path attackers โœจ no cap, that's a whole lot of defense

16.1. Interaction with IPSec ๐Ÿ”๐Ÿฆ‹

okay so Shim6 has two ways of processing data packets ๐Ÿ’… if the ULID pair is also the locator pair being used, the data packet isn't modified by Shim6 at all. in that case, the interaction with IPSec is exactly the same as if the Shim6 layer weren't in the host ๐ŸŒˆ

if the ULID pair is different from the current locator pair for that Shim6 context, then Shim6 takes the data packet, swaps the ULIDs in the IP Source and Destination Address fields for the current locator pair, and adds the Shim6 extension with the matching Context Tag ๐Ÿช„ here, like we mentioned in Section 1.6, Shim6 works kinda like a tunnel mechanism, where the inner header has the ULID and the outer header has the locators. the big difference is that the inner header gets "compressed," and a compression tag (the Context Tag) is added so the receiving end can decompress it ๐ŸŽ

so the interaction between IPSec and Shim6 is then similar to the one between IPSec and a tunnel mechanism ๐Ÿ’œ when the upper-layer protocol generates the packet, it gets passed to the IP layer with the ULIDs in the IP Source and Destination Address fields. IPSec is applied to that packet, and then the packet goes to the Shim6 sublayer, which "encapsulates" it and adds a new IP header with the locator pair in the IP Source and Destination Address fields. this new IP packet then goes back to IPSec for processing, just like with a tunnel. it's like IPSec is sitting both above and below the Shim6 sublayer, and IPSec policies apply to both ULIDs and locators. main character energy ๐Ÿ‘‘

when IPSec processes the packet after the Shim6 sublayer has handled it (so the packet carries the locators in the IP Source and Destination Address fields), the Shim6 sublayer may have added the Shim6 Extension header ๐Ÿ™ƒ in that case IPSec needs to skip past the Shim6 Extension header to find the selectors for the next layer's protocols (for example, TCP, UDP, or Stream Control Transmission Protocol (SCTP)) ๐Ÿ“

when a packet arrives at the other end, it's processed based on the order of the extension headers ๐Ÿงฉ so if an ESP or AH header comes before a Shim6 header, that order decides things. Shim6 adds the need to do policy checks, similar to how they're done for tunnels, when Shim6 gets a packet whose ULID pair isn't identical to the locator pair in the packet ๐Ÿ’€ ngl, lots of checks going on


16.2. Residual Threats ๐Ÿ˜ฌ๐ŸŒง๏ธ

some of the leftover threats in this proposal are:

  • an attacker that shows up late on the path (after the context is already established) can use the R1bis message to make one peer re-create the context. at that moment, they can watch the whole exchange ๐Ÿ‘€ but this doesn't seem to open any new doors, because an attacker like that can already see the Context Tags being used and, once they know them, can use them to send bogus messages. not ideal, but not a whole new disaster
  • an attacker who was on the path to find the Context Tags can generate an R1bis message after they've moved off the path ๐Ÿƒโ€โ™€๏ธ for this packet to work, it needs a source locator that belongs to the context. so there can't be "too much" ingress filtering between the attacker's new location and the communicating peers. it doesn't seem that severe, though, because once the R1bis causes the context to be re-established, a new pair of Context Tags gets used, and the attacker won't know them. if this is still a concern, we could require a 2-way handshake, "did you really lose the state?", in response to the error message ๐Ÿค
  • it might be possible for an attacker to try random 47-bit Context Tags and see if they can disrupt communication between two hosts ๐ŸŽฒ for payload packets, the effects would be similar to an attacker sending packets with a spoofed source address. for control packets, finding the right Context Tag isn't enough, because extra info is needed too (for example, nonces, or proper source addresses; see the previous bullet for the R1bis case). if a 47-bit tag, which is the largest that fits in an 8-octet Extension header, isn't enough, one could use an even larger tag in the Shim6 control messages and use the low-order 47 bits in the Shim6 Payload Extension header ๐Ÿง 
  • when the Shim6 Payload Extension header is used, an attacker who can guess the 47-bit random Context Tag can inject packets into the context with any source locator ๐Ÿ˜ฑ so if there's ingress filtering between the attacker and their target, this could potentially let the attacker get around that filtering. BUT, in addition to guessing the 47-bit Context Tag, the attacker also has to find a context where the ULP checksum is correct after the receiver swaps the locators back to the ULIDs ๐Ÿงฎ and even that wouldn't be enough with ULPs like TCP, since the TCP port numbers and sequence numbers have to match an existing connection. so even though off-path attackers injecting packets is a different situation than today with ingress filtering, it's still very hard for an off-path attacker to guess right ๐Ÿ’ช and if IPsec is applied, the issue goes away completely โœจ
  • the validator included in the R1 and R1bis packets is generated as a hash of several input parameters ๐Ÿ”ข most of the inputs are determined by the sender, and only the secret value S is unknown to the sender. the protection is still considered enough, since it'd be easier for the attacker to just get a new validator by sending an I1 packet than to do all the computations needed to figure out the secret S ๐Ÿ™…โ€โ™€๏ธ still, it is recommended that the host change the secret S periodically ๐Ÿ”„ bestie, rotate those secrets!! ๐Ÿซถ

17. IANA Considerations โœจ

okay bestie, IANA is the org that keeps all the protocol numbers and registries straight, so this section is basically them telling everyone what they've got on file ๐Ÿ“‹๐Ÿ’…

IANA allocated a new IP Protocol Number value (140) for the Shim6 Protocol. ๐Ÿฆ‹

IANA recorded a CGA message type for the Shim6 protocol in the CGA Extension Type Tags registry with the value 0x4A30 5662 4858 574B 3655 416F 506A 6D48. ๐ŸŒธ

IANA established a Shim6 Parameter Registry with four components: Shim6 Type registrations, Shim6 Options registrations, Shim6 Error Code registrations, and Shim6 Verification Method registrations. It's giving organized ๐Ÿ—‚๏ธโœจ

The initial contents of the Shim6 Type registry are as follows:

   +------------+-----------------------------------------------------+
   | Type Value |                       Message                       |
   +------------+-----------------------------------------------------+
   |      0     |                       RESERVED                      |
   |      1     | I1 (first establishment message from the initiator) |
   |      2     | R1 (first establishment message from the responder) |
   |      3     |  I2 (2nd establishment message from the initiator)  |
   |      4     |  R2 (2nd establishment message from the responder)  |
   |      5     |  R1bis (Reply to reference to non-existent context) |
   |      6     |           I2bis (Reply to a R1bis message)          |
   |    7-59    |           Allocated using Standards action          |
   |    60-63   |                 For Experimental use                |
   |     64     |                    Update Request                   |
   |     65     |                Update Acknowledgement               |
   |     66     |                      Keepalive                      |
   |     67     |                    Probe Message                    |
   |     68     |                    Error Message                    |
   |   69-123   |           Allocated using Standards action          |
   |   124-127  |                 For Experimental use                |
   +------------+-----------------------------------------------------+

The initial contents of the Shim6 Options registry are as follows:

            +-------------+----------------------------------+
            |     Type    |            Option Name           |
            +-------------+----------------------------------+
            |      0      |             RESERVED             |
            |      1      |        Responder Validator       |
            |      2      |           Locator List           |
            |      3      |        Locator Preferences       |
            |      4      |   CGA Parameter Data Structure   |
            |      5      |           CGA Signature          |
            |      6      |             ULID Pair            |
            |      7      |    Forked Instance Identifier    |
            |     8-9     | Allocated using Standards action |
            |      10     |     Keepalive Timeout Option     |
            |   11-16383  | Allocated using Standards action |
            | 16384-32767 |       For Experimental use       |
            +-------------+----------------------------------+

The initial contents of the Shim6 Error Code registry are as follows:

        +------------+--------------------------------------------+
        | Code Value |                 Description                |
        +------------+--------------------------------------------+
        |      0     |         Unknown Shim6 message type         |
        |      1     |       Critical Option not recognized       |
        |      2     |     Locator verification method failed     |
        |      3     | Locator List Generation number out of sync |
        |      4     |       Error in the number of locators      |
        |    5-19    |      Allocated using Standards action      |
        |   120-127  |       Reserved for debugging purposes      |
        +------------+--------------------------------------------+

The initial contents of the Shim6 Verification Method registry are as follows:

              +---------+----------------------------------+
              |  Value  |        Verification Method       |
              +---------+----------------------------------+
              |    0    |             RESERVED             |
              |    1    |                CGA               |
              |    2    |                HBA               |
              |  3-200  | Allocated using Standards action |
              | 201-254 |       For Experimental use       |
              |   255   |             RESERVED             |
              +---------+----------------------------------+

18. Acknowledgements ๐Ÿซถ

Over the years, a bunch of people from the multi6 and shim6 working groups have dropped ideas and suggestions that ended up in this spec, and they deserve all the flowers ๐ŸŒท Special thanks to the careful comments from Sam Hartman, Cullen Jennings, Magnus Nystrom, Stephen Kent, Geoff Huston, Shinta Sugimoto, Pekka Savola, Dave Meyer, Deguang Le, Jari Arkko, Iljitsch van Beijnum, Jim Bound, Brian Carpenter, Sebastien Barre, Matthijs Mekking, Dave Thaler, Bob Braden, Wesley Eddy, Pasi Eronen, and Tom Henderson on earlier versions of this document. ๐Ÿ’œ


19. References ๐Ÿ“š

19.1. Normative References

  • [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [2] Aura, T., "Cryptographically Generated Addresses (CGA)", RFC 3972, March 2005.
  • [3] Bagnulo, M., "Hash-Based Addresses (HBA)", RFC 5535, June 2009.
  • [4] Arkko, J. and I. van Beijnum, "Failure Detection and Locator Pair Exploration Protocol for IPv6 Multihoming", RFC 5534, June 2009.

19.2. Informative References

  • [5] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, February 2000.
  • [6] Ferguson, P. and D. Senie, "Network Ingress Filtering: Defeating Denial of Service Attacks which employ IP Source Address Spoofing", BCP 38, RFC 2827, May 2000.
  • [7] Draves, R., "Default Address Selection for Internet Protocol version 6 (IPv6)", RFC 3484, February 2003.
  • [8] Nordmark, E., "Multihoming without IP Identifiers", Work in Progress, July 2004.
  • [9] Bagnulo, M., "Updating RFC 3484 for multihoming support", Work in Progress, November 2007.
  • [10] Schulzrinne, H., Casner, S., Frederick, R., and V. Jacobson, "RTP: A Transport Protocol for Real-Time Applications", STD 64, RFC 3550, July 2003.
  • [11] Abley, J., Black, B., and V. Gill, "Goals for IPv6 Site-Multihoming Architectures", RFC 3582, August 2003.
  • [12] Rajahalme, J., Conta, A., Carpenter, B., and S. Deering, "IPv6 Flow Label Specification", RFC 3697, March 2004.
  • [13] Eastlake, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.
  • [14] Hinden, R. and B. Haberman, "Unique Local IPv6 Unicast Addresses", RFC 4193, October 2005.
  • [15] Nordmark, E. and T. Li, "Threats Relating to IPv6 Multihoming Solutions", RFC 4218, October 2005.
  • [16] Huitema, C., "Ingress filtering compatibility for IPv6 multihomed sites", Work in Progress, September 2005.
  • [17] Bagnulo, M. and E. Nordmark, "SHIM - MIPv6 Interaction", Work in Progress, July 2005.
  • [18] Nordmark, E., "Shim6-Application Referral Issues", Work in Progress, July 2005.
  • [19] Bagnulo, M. and J. Abley, "Applicability Statement for the Level 3 Multihoming Shim Protocol (Shim6)", Work in Progress, July 2007.
  • [20] Moskowitz, R., Nikander, P., Jokela, P., and T. Henderson, "Host Identity Protocol", RFC 5201, April 2008.
  • [21] Schuetz, S., Koutsianas, N., Eggert, L., Eddy, W., Swami, Y., and K. Le, "TCP Response to Lower-Layer Connectivity-Change Indications", Work in Progress, February 2008.
  • [22] Williams, N. and M. Richardson, "Better-Than-Nothing Security: An Unauthenticated Mode of IPsec", RFC 5386, November 2008.
  • [23] Komu, M., Bagnulo, M., Slavov, K., and S. Sugimoto, "Socket Application Program Interface (API) for Multihoming Shim", Work in Progress, November 2008.
  • [24] Mathis, M. and J. Heffner, "Packetization Layer Path MTU Discovery", RFC 4821, March 2007.
  • [25] Bonica, R., Gan, D., Tappan, D., and C. Pignataro, "Extended ICMP to Support Multi-Part Messages", RFC 4884, April 2007.

Appendix A. Possible Protocol Extensions โœจ

Okay bestie, this appendix is basically the "wishlist for later" ๐Ÿ“๐Ÿ’– While building this protocol, the crew kept running into stuff that was important but didn't need to live in the base protocol, so they got parked here as possible extensions ๐Ÿ’… The big ones are:

  • As the assumptions in Section 3 point out, Shim6 needs to recover from a wide range of failures (for instance, when one of the communicating hosts is single-homed) and cope with a site's ISPs doing ingress filtering based on the source IPv6 address. That means the host needs to be able to influence the egress selection from its site ๐ŸŒธ More discussion of this lives in [16].
  • Do we need to keep the list of locators private between the two communicating endpoints? ๐Ÿค” We could maybe pull that off when using CGA (not when using HBA), but it would cost some public key encryption and decryption operations during context establishment. The suggestion is to leave this for a future extension ๐Ÿ”ฎ
  • Defining some kind of end-to-end "compression" mechanism that removes the need to include the Shim6 Payload Extension header when the locator pair is not the ULID pair ๐Ÿ—œ๏ธโœจ
  • Supporting dynamic setting of locator preferences on a site-wide basis, and using the Locator Preference option in the Shim6 protocol to tell remote communicating hosts about those preferences. This could mirror the DNS SRV record's notion of priority and weight ๐ŸŽ€
  • Specifying APIs so the ULPs can be aware of the locators the shim is using and influence which locators get chosen (controlling preferences as well as triggering a locator-pair switch). This includes APIs the ULPs can use to fork a shim context ๐Ÿ‘‘
  • Figuring out whether it's feasible to relax the suggestions for when context state gets removed, so you can end up with an asymmetric distribution of context state and still get (most of) the shim benefits ๐Ÿฆ‹ Picture this: the busy server goes through context setup but quickly removes the context state to save memory, while the not-so-busy client keeps it. The context-recovery mechanism in Section 7.5 would then re-create the state if the client sends either a shim control message (like a Probe message because it sees a problem) or a ULP packet in a Shim6 Payload Extension header (because it had earlier failed over to an alternative locator pair and then went quiet for a while). This seems to give you the benefits of the shim as long as the client can detect the failure. BUT if the client doesn't send anything and it's the server trying to send, the server can't recover, because its shim has no context state and therefore doesn't know any alternate locator pairs ๐Ÿ˜ญ
  • Studying what it would take to make the Shim6 control protocol not rely at all on a stable source locator in the packets. This can probably be done by having all the shim control messages include the ULID-pair option ๐Ÿงš
  • If each host might have lots of locators, then the current requirement to include essentially all of them in the I2 and R2 messages could be kind of constraining ๐Ÿ™ˆ If that's the case, we could look into using the CGA Parameter Data Structure for the comparison, instead of the prefix sets, to detect context confusion. This would put some constraint on a (logical) host only using, for example, one CGA public key, and it would also need some carefully crafted rules for how two PDSs get compared for "being the same host". But if we don't expect more than a handful of locators per host, we don't need this extra complexity ๐Ÿ’…
  • ULP-specified timers for the reachability detection mechanism (which can be especially useful when there are forked contexts) โฑ๏ธ
  • Pre-verifying some "backup" locator pair, so the failover time can be shorter ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ
  • Studying how Shim6 and Mobile IPv6 might interact [17] ๐Ÿ“ฑ

Appendix B. Simplified STATE Machine ๐Ÿงฉ

The STATEs are defined in Section 6.2. The stylized description below is meant to be consistent with the textual description in the spec, BUT if they ever conflict, the textual description is the normative one ๐Ÿซถ So the tables below are the quick-glance version, and the words win if there's a mismatch.

Here are the possible actions in STATE IDLE and their triggers ๐ŸŒˆ

+---------------------+---------------------------------------------+
| Trigger             | Action                                      |
+---------------------+---------------------------------------------+
| Receive I1          | Send R1 and stay in IDLE                    |
|                     |                                             |
| Heuristics trigger  | Send I1 and move to I1-SENT                 |
| a new context       |                                             |
| establishment       |                                             |
|                     |                                             |
| Receive I2, verify  | If successful, send R2 and move to          |
| validator and       | ESTABLISHED                                 |
| RESP Nonce          |                                             |
|                     | If fail, stay in IDLE                       |
|                     |                                             |
| Receive I2bis,      | If successful, send R2 and move to          |
| verify validator    | ESTABLISHED                                 |
| and RESP Nonce      |                                             |
|                     | If fail, stay in IDLE                       |
|                     |                                             |
| R1, R1bis, R2       | N/A (This context lacks the required info   |
|                     | for the dispatcher to deliver them)         |
|                     |                                             |
| Receive Payload     | Send R1bis and stay in IDLE                 |
| Extension header    |                                             |
| or other control    |                                             |
| packet              |                                             |
+---------------------+---------------------------------------------+

Next up, here are the possible actions in STATE I1-SENT and their triggers ๐Ÿฆ‹

+---------------------+---------------------------------------------+
| Trigger             | Action                                      |
+---------------------+---------------------------------------------+
| Receive R1, verify  | If successful, send I2 and move to I2-SENT  |
| INIT Nonce          |                                             |
|                     | If fail, discard and stay in I1-SENT        |
|                     |                                             |
| Receive I1          | Send R2 and stay in I1-SENT                 |
|                     |                                             |
| Receive R2, verify  | If successful, move to ESTABLISHED          |
| INIT Nonce          |                                             |
|                     | If fail, discard and stay in I1-SENT        |
|                     |                                             |
| Receive I2, verify  | If successful, send R2 and move to          |
| validator and RESP  | ESTABLISHED                                 |
| Nonce               |                                             |
|                     | If fail, discard and stay in I1-SENT        |
|                     |                                             |
| Receive I2bis,      | If successful, send R2 and move to          |
| verify validator    | ESTABLISHED                                 |
| and RESP Nonce      |                                             |
|                     | If fail, discard and stay in I1-SENT        |
|                     |                                             |
| Timeout, increment  | If counter =< I1_RETRIES_MAX, send I1 and   |
| timeout counter     | stay in I1-SENT                             |
|                     |                                             |
|                     | If counter > I1_RETRIES_MAX, go to E-FAILED |
|                     |                                             |
| Receive ICMP payload| Move to E-FAILED                            |
| unknown error       |                                             |
|                     |                                             |
| R1bis               | N/A (Dispatcher doesn't deliver since       |
|                     | CT(peer) is not set)                        |
|                     |                                             |
| Receive Payload     | Discard and stay in I1-SENT                 |
| Extension header    |                                             |
| or other control    |                                             |
| packet              |                                             |
+---------------------+---------------------------------------------+

Now for STATE I2-SENT and its triggers ๐ŸŒธ

Okay bestie, so we're still in Appendix B ๐Ÿ’œ and this first table is for when a peer is in I2-SENT ๐Ÿฆ‹ Read the Trigger column, then the Action column, and you've basically got it โœจ

   +---------------------+---------------------------------------------+
   | Trigger             | Action                                      |
   +---------------------+---------------------------------------------+
   | Receive R2, verify  | If successful, move to ESTABLISHED          |
   | INIT Nonce          |                                             |
   |                     | If fail, stay in I2-SENT                    |
   |                     |                                             |
   | Receive I1          | Send R2 and stay in I2-SENT                 |
   |                     |                                             |
   | Receive I2,         | Send R2 and stay in I2-SENT                 |
   | verify validator    |                                             |
   | and RESP Nonce      |                                             |
   |                     |                                             |
   | Receive I2bis,      | Send R2 and stay in I2-SENT                 |
   | verify validator    |                                             |
   | and RESP Nonce      |                                             |
   |                     |                                             |
   | Receive R1          | Discard and stay in I2-SENT                 |
   |                     |                                             |
   | Timeout, increment  | If counter =< I2_RETRIES_MAX, send I2 and   |
   | timeout counter     | stay in I2-SENT                             |
   |                     |                                             |
   |                     | If counter > I2_RETRIES_MAX, send I1 and go |
   |                     | to I1-SENT                                  |
   |                     |                                             |
   | R1bis               | N/A (Dispatcher doesn't deliver since       |
   |                     | CT(peer) is not set)                        |
   |                     |                                             |
   | Receive Payload     | Accept and send I2 (probably R2 was sent    |
   | Extension header    | by peer and lost)                           |
   | or other control    |                                             |
   | packet              |                                             |
   +---------------------+---------------------------------------------+

Next up is I2BIS-SENT ๐ŸŒธ It's basically the same drama as I2-SENT, just with I2bis showing up in the replies instead of I2 ๐Ÿซถ

   +---------------------+---------------------------------------------+
   | Trigger             | Action                                      |
   +---------------------+---------------------------------------------+
   | Receive R2, verify  | If successful, move to ESTABLISHED          |
   | INIT Nonce          |                                             |
   |                     | If fail, stay in I2BIS-SENT                 |
   |                     |                                             |
   | Receive I1          | Send R2 and stay in I2BIS-SENT              |
   |                     |                                             |
   | Receive I2,         | Send R2 and stay in I2BIS-SENT              |
   | verify validator    |                                             |
   | and RESP Nonce      |                                             |
   |                     |                                             |
   | Receive I2bis,      | Send R2 and stay in I2BIS-SENT              |
   | verify validator    |                                             |
   | and RESP Nonce      |                                             |
   |                     |                                             |
   | Receive R1          | Discard and stay in I2BIS-SENT              |
   |                     |                                             |
   | Timeout, increment  | If counter =< I2_RETRIES_MAX, send I2bis    |
   | timeout counter     | and stay in I2BIS-SENT                      |
   |                     |                                             |
   |                     | If counter > I2_RETRIES_MAX, send I1 and    |
   |                     | go to I1-SENT                               |
   |                     |                                             |
   | R1bis               | N/A (Dispatcher doesn't deliver since       |
   |                     | CT(peer) is not set)                        |
   |                     |                                             |
   | Receive Payload     | Accept and send I2bis (probably R2 was      |
   | Extension header    | sent by peer and lost)                      |
   | or other control    |                                             |
   | packet              |                                             |
   +---------------------+---------------------------------------------+

Now the main character state ๐Ÿ‘‘ ESTABLISHED is where everything is actually happening ๐Ÿ’… Pay attention to the I1 row, because it's the one that compares CT(peer) with the received CT โœจ

   +---------------------+---------------------------------------------+
   | Trigger             | Action                                      |
   +---------------------+---------------------------------------------+
   | Receive I1, compare | If no match, send R1 and stay in ESTABLISHED|
   | CT(peer) with       |                                             |
   | received CT         | If match, send R2 and stay in ESTABLISHED   |
   |                     |                                             |
   |                     |                                             |
   | Receive I2, verify  | If successful, send R2 and stay in          |
   | validator and RESP  | ESTABLISHED                                 |
   | Nonce               |                                             |
   |                     | Otherwise, discard and stay in ESTABLISHED  |
   |                     |                                             |
   | Receive I2bis,      | If successful, send R2 and stay in          |
   | verify validator    | ESTABLISHED                                 |
   | and RESP Nonce      |                                             |
   |                     | Otherwise, discard and stay in ESTABLISHED  |
   |                     |                                             |
   | Receive R2          | Discard and stay in ESTABLISHED             |
   |                     |                                             |
   | Receive R1          | Discard and stay in ESTABLISHED             |
   |                     |                                             |
   | Receive R1bis       | Send I2bis and move to I2BIS-SENT           |
   |                     |                                             |
   |                     |                                             |
   | Receive Payload     | Process and stay in ESTABLISHED             |
   | Extension header    |                                             |
   | or other control    |                                             |
   | packet              |                                             |
   |                     |                                             |
   | Implementation-     | Discard state and go to IDLE                |
   | specific heuristic  |                                             |
   | (e.g., No open ULP  |                                             |
   | sockets and idle    |                                             |
   | for some time )     |                                             |
   +---------------------+---------------------------------------------+

Next is E-FAILED ๐Ÿฅบ It's a little cooldown spot. You just wait out NO_R1_HOLDDOWN_TIME and then you're back to IDLE, or you process any packet the same way IDLE would ๐Ÿงš

   +---------------------+---------------------------------------------+
   | Trigger             | Action                                      |
   +---------------------+---------------------------------------------+
   | Wait for            | Go to IDLE                                  |
   | NO_R1_HOLDDOWN_TIME |                                             |
   |                     |                                             |
   | Any packet          | Process as in IDLE                          |
   +---------------------+---------------------------------------------+

And last but not least, NO-SUPPORT ๐Ÿ’€ This one is the same vibe as E-FAILED, except the timer is ICMP_HOLDDOWN_TIME instead ๐Ÿ™ˆ

   +---------------------+---------------------------------------------+
   | Trigger             | Action                                      |
   +---------------------+---------------------------------------------+
   | Wait for            | Go to IDLE                                  |
   | ICMP_HOLDDOWN_TIME  |                                             |
   |                     |                                             |
   | Any packet          | Process as in IDLE                          |
   +---------------------+---------------------------------------------+

B.1. Simplified STATE Machine Diagram โœจ

                                          Timeout/Null    +------------+
                            I1/R1      +------------------| NO SUPPORT |
            Payload or Control/R1bis   |                  +------------+
                        +---------+    |                              ^
                        |         |    |               ICMP Error/Null|
                        |         V    V                              |
                      +-----------------+  Timeout/Null  +----------+ |
                      |                 |<---------------| E-FAILED | |
                    +-|      IDLE       |                +----------+ |
     I2 or I2bis/R2 | |                 |                          ^  |
                    | +-----------------+       (Tiemout#>MAX)/Null|  |
                    |    ^            |                            |  |
                    |    |            +------+                     |  |
   I2 or I2bis/R2   |    |       Heuristic/I1|            I1/R2    |  |
     Payload/Null   |    |                   |       Control/Null  |  |
      I1/R1 or R2   | +--+                   |       Payload/Null  |  |
    R1 or R2/Null   | |Heuristic/Null        |  (Tiemout#<MAX)/I1  |  |
      +----------+  | |                      |         +--------+  |  |
      |          V  V |                      |         |        V  |  |
    +-------------------+   R2/Null          |        +----------------+
    |                   |   I2 or I2bis/R2   +------->|                |
    |   ESTABLISHED     |<----------------------------|    I1-SENT     |
    |                   |                             |                |
    +-------------------+                             +----------------+
       |     ^        ^                                   |   ^       ^
       |     |        |R2/Null              +-------------+   |       |
       |     |        +----------+          |R1/I2            |       |
       |     |                   |          V                 |       |
       |     |               +------------------+             |       |
       |     |               |                  |-------------+       |
       |     |               |     I2-SENT      | (Timeout#>Max)/I1   |
       |     |               |                  |                     |
       |     |               +------------------+                     |
       |     |                 |              ^                       |
       |     |                 +--------------+                       |
       |     |                I1 or I2bis or I2/R2                    |
       |     |           (Timeout#<Max) or Payload/I2                 |
       |     |                 R1 or R1bis/Null                       |
       |     +-------+                              (Timeout#>Max)/I1 |
       |      R2/Null|     +------------------------------------------+
       |             V     |
       |         +-------------------+
       |         |                   |<-+ (Timeout#<Max)/I2bis
       +-------->|   I2bis-SENT      |  | I1 or I2 or I2bis/R2
     R1bis/I2bis |                   |--+ R1 or R1bis/Null
                 +-------------------+    Payload/I2bis

Appendix C. Context Tag Reuse ๐ŸŽ€

Okay so the Shim6 protocol doesn't have a way for both peers to coordinate removing state at the same time ๐Ÿ™ˆ and honestly that's fine, because removing state wouldn't really help anyway. A host can crash and reboot at any moment, so the protocol has to be robust even when a Context Tag gets reused for some totally different context. This appendix walks through all the different ways a Tag can get reused and how recovery works in each case ๐Ÿ’–

Let's look at one example to make it click. Say hosts A and B are chatting using a context with the ULID pair <A1, B2>, and B gave that context Context Tag X. We're assuming B only uses the Context Tag to demultiplex the received Shim6 Payload Extension headers, because that's the more general situation. Next, B removes this context state, but A keeps it. Later on, B might assign CT(local)=X to some other context, and at that point there are a few possible cases:

  • The Context Tag is reassigned to a context for the same ULID pair <A1, B2>. We've called this "context recovery" in this document.
  • The Context Tag is reassigned to a context for a different ULID pair between the same two hosts, e.g., <A3, B3>. We've called this "context confusion" in this document.
  • The Context Tag is reassigned to a context between B and another host C, for instance, for the ULID pair <C3, B2>. That is a form of three-party context confusion.

C.1. Context Recovery ๐ŸŒธ

This one is pretty chill and gets covered in Section 7.5. The key thing is that the ULID pair is the same. So when either A or B tries to set up the new context, A can just keep its old context while B re-creates the context with the same Context Tag CT(B) = X. Easy peasy ๐Ÿงš

C.2. Context Confusion ๐Ÿฆ‹

This case is a bit more complicated and gets discussed in Section 7.6. When the new context gets created, it doesn't matter whether A or B starts it. Host A can notice when it receives B's locator set (in the I2 or R2 message), because it ends up with two contexts to the same peer host (overlapping Ls(peer) locator sets) that both have the same Context Tag: CT(peer) = X. At that point, host A can clear up any chance of confusion by not using the old context to send any more packets. It can either just discard the old context (no ULP traffic might be using it, since B had already discarded it), or it can re-create a different context for the old ULID pair (<A1, B2>), and B will assign a unique CT(B) as part of the normal context-establishment mechanism. ๐Ÿ’…

C.3. Three-Party Context Confusion ๐Ÿ˜ญ

This third case is a little trickier, because there's no spot where the old state on A can be verified. The new context is established between B and C, so there's nothing on A's side to check it against. So when B receives Shim6 Payload Extension headers with X as the Context Tag, it finds the context for <C3, B2> and rewrites the packets to have C3 in the Source Address field and B2 in the Destination Address field before passing them up to the ULP. That rewriting is correct when the packets really are sent by host C. But if host A ever happens to send a packet using the old context, then the ULP on A sends a packet with ULIDs <A1, B2>, and that packet reaches the ULP on B with ULIDs <C3, B2>. Yikes ๐Ÿ™ˆ

This is clearly an error, and the packet will most likely get rejected by the ULP on B because of a bad pseudo-header checksum. Even if the checksum happens to be okay (probability 2^-16), the ULP probably won't have a connection for those ULIDs and port numbers. And if the ULP is connection-less, processing the packet is most likely harmless, since a ULP like that has to be able to cope with random packets from random peers anyway ๐Ÿซถ

The broken state, where packets go from A to B using the old context on host A, might stick around for a little while, but it won't last very long. The unreachability detection on host A will kick in because it stops seeing any return traffic (payload or Keepalive messages) for the context. That makes host A send Probe messages to host B to find a working locator pair. As a result, host B notices it doesn't have a context for the ULID pair <A1, B2> and CT(B) = X, so it sends an R1bis packet to re-establish that context. Just like in the previous section, the re-established context gets a unique CT(B) assigned by host B, so the confusion is gone for good โœจ

C.4. Summary ๐Ÿ“

So, in summary, there are cases where a Context Tag might get reused while some peer still holds the state, but the protocol can recover from it. These events are pretty unlikely, given the 47-bit Context Tag size. Still, it's really important that these recovery mechanisms get tested ๐Ÿ‘‘ That's why, during development and testing, it is recommended that implementations don't use the full 47-bit space. Instead, they should keep, for example, the top 40 bits as zero, which only leaves the host with 128 unique Context Tags. That way the recovery mechanisms get exercised a lot more often ๐Ÿงช

Appendix D. Design Alternatives ๐Ÿ’…

Real talk, this document picked one particular set of design choices so it could work out a bunch of the details and get people talking. But, as has come up on the mailing list, there are other choices that make sense too. This appendix tries to list some of those alternatives ๐ŸŒˆ

D.1. Context Granularity ๐Ÿฆ‹

For a while now, people have been wondering whether the shim should know about ULP connections and sessions, even though it works at the IP layer. If it did, it could make separate shim contexts for separate ULP connections and sessions. A few different options have come up:

  • Each ULP connection maps to its own shim context.
  • The shim is unaware of the ULP notion of connections and just operates on a host-to-host (IP address) granularity.
  • Hybrids in which the shim is aware of some ULPs (such as TCP) and handles other ULPs on a host-to-host basis.

Having shim state for every ULP connection could mean higher overhead, since the state-setup cost might add up to something significant. There's real value in being able to spread that cost across multiple connections ๐Ÿงš

On the flip side, being totally unaware of ULP connections might get in the way of ULPs that want different communication to use different locator pairs, for instance, for quality or cost reasons ๐Ÿค”

The protocol goes with a shim that operates at host-level granularity (strictly speaking, at ULID-pair granularity) so it can amortize the context establishment over multiple ULP connections. To make up for that, Shim6-aware ULPs can request context forking, so that different ULP traffic can use different locator pairs ๐Ÿซถ

D.2. Demultiplexing of Data Packets in Shim6 Communications โœจ

okay so once a ULID-pair context is set up between two hosts, the packets can carry locators that are different from the ULIDs the ULPs are actually looking at ๐Ÿ‘€ the Shim6 layer's whole main job is mapping between the locators used to forward packets through the network and the ULIDs shown to the ULP. ๐Ÿ’… so for incoming packets, the shim has to first figure out which ones need translating, and then do the locator-to-ULID mapping using the matching context. that identifying step is called "demultiplexing" ๐Ÿงš and it's giving tricky, because any address can be used as a locator AND as a ULID, so you have to look at more than just the addresses in the packet.

for example, say a host has addresses A1 and A2 and starts talking to a peer with B1 and B2. ๐ŸŒธ some connections might use the pair <A1, B1> as ULIDs, and others might use <A2, B2>, for example. at the start there are no failures, so those pairs are just used as locators, which means they're sitting in the IP address fields on the wire. but when something breaks, the Shim6 layer on A might decide to send the packets that used <A1, B1> as ULIDs with <A2, B2> as the locators instead. ๐Ÿ˜ญ now B has to rewrite the IP address field for some packets and not others, even though all of them have the same locator pair. chaotic, I know ๐Ÿ’€

so to make demultiplexing actually work, data packets carry a Context Tag. ๐ŸŽ€ that tag tells the receiver which shim context to use for the operation.

there were two ways to carry the Context Tag that got a serious look during the shim protocol design: putting it in the Flow Label field of the IPv6 header, or using a brand new Extension header. ๐Ÿฆ‹ this appendix walks through the pros and cons of each one and explains why the chosen option won ๐Ÿ‘‘

D.2.1. Flow Label

okay, first option: carry the Context Tag in the Flow Label field of the IPv6 header ๐ŸŒˆ that means when a Shim6 context gets established, a Flow Label value gets tied to that context (and maybe a separate Flow Label for each direction).

the simplest version is to have the triple <Flow Label, Source Locator, Destination Locator> identify the context at the receiver. ๐Ÿ’–

the catch? the locator sets are dynamic, so at any given moment you can't be sure that two contexts given the same Context Tag will still have disjoint locator sets for their whole lifetime. ๐Ÿ˜ฌ

let's make it concrete. Node A has addresses IPA1, IPA2, IPA3, and IPA4, and Host B has IPB1 and IPB2.

now picture two different contexts between Host A and Host B.

Context #1 uses IPA1 and IPB1 as ULIDs. The locator set for IPA1 is IPA1 and IPA2, and the locator set for IPB1 is just IPB1.

Context #2 uses IPA3 and IPB2 as ULIDs. The locator set for IPA3 is IPA3 and IPA4, and the locator set for IPB2 is just IPB2.

since the locator sets of Context #1 and Context #2 are disjoint, the hosts could think it's totally fine to give both of them the same Context Tag value. ๐Ÿ™ˆ but then, later on, IPA3 gets added as a valid locator for IPA1 in Context #2, and IPB2 gets added as a valid locator for IPB1 in Context #1. ๐Ÿ’€ now the triple <Flow Label, Source Locator, Destination Locator> doesn't identify a unique context anymore, and correct demultiplexing is no longer possible. not slay at all.

one way to dodge this is to just never repeat Flow Label values for any communication set up in a host. ๐Ÿ“ basically, every time a new communication using different ULIDs gets established, it gets a brand new Flow Label value. then each of those communications can be told apart, because each one has its own value.

the problem with that? the receiver has to allocate the Flow Label value used for incoming packets so they're all unique, which means a shim negotiation of the Flow Label value has to happen before any data packets get exchanged. ngl that causes problems with non-Shim6-capable hosts, since they can't negotiate an acceptable Flow Label value. ๐Ÿ˜ค this can be fixed by marking which packets belong to shim sessions and which don't. those markings would need at least one bit in the IPv6 header that isn't currently available, so you'd need more creative options. for example, you could use new Next Header values to show that a packet belongs to a Shim6-enabled communication and that its Flow Label carries context information, as proposed in [8]. however, even with new Next Header values like that, this approach is incompatible with the deferred-establishment capability of the shim protocol. ๐Ÿฅบ that capability is a preferred function, because it avoids delay from setting up the shim context before communication starts. it also lets nodes decide, based on their own policies, at which stage of the communication a given communication needs shim protection. ๐Ÿซถ

so to work around all of that, there's another approach ๐Ÿ”ฅ it doesn't restrict the Flow Label values used by communications whose ULIDs equal their locators (so, no shim translation). the only requirement is that different Flow Label values get assigned to different shim contexts. in this setup, communications start with unmodified Flow Label usage (it could be zero, or as suggested in [12]). the packets sent after a failure, when a different locator pair is in use, would use a completely different Flow Label, and the receiver can allocate that one as part of the shim context establishment. since it's allocated during context establishment, the receiver of the "failed over" packets can pick any Flow Label it likes, as long as it's unique in the sense that no other context is using it as a Context Tag. and there's no performance impact! โœจ the one thing to keep in mind is that, for each locator pair, the Flow Label value used for that pair doesn't change because of the multihoming shim.

the constraint here is that Flow Label values being used as context identifiers can't be used by other communications with non-disjoint locator sets. ๐ŸŒธ so once a Flow Label value has been assigned to a shim context with certain locator sets, that same value can't be used for any other communication that uses an address pair contained in those locator sets. it's a constraint on the possible Flow Label allocation strategies, and that's the tradeoff. ๐Ÿ‘‘

there's a possible workaround for this constraint too ๐Ÿฆ‹ mark the shim packets that need translating so they're different from regular IPv6 packets, using the artificial Next Header values described above. then the only Flow Label values that are constrained are the ones on packets the shim is actually translating. ๐Ÿ˜Œ honestly, this last approach would be the preferred one if the Context Tag is carried in the Flow Label field. not only does it impose the minimum constraints on Flow Label allocation (only the packets that need translating are restricted), it also helps context-loss detection a lot. why? because shim data packets are identified as such, the receiving end can tell whether a shim context associated with a received packet is supposed to exist. ๐Ÿง  more on that in the context-loss detection appendix below ๐Ÿ’œ

D.2.2. Extension Header

okay, the second approach is the one this protocol actually picked ๐ŸŽ€ carry the Context Tag in a new Extension header. these Context Tags get allocated by the receiving end during the initial Shim6 protocol negotiation, so each context ends up with two Context Tags, one per direction. data packets get demultiplexed using the Context Tag in the Extension header. ๐Ÿ’…

this seems like a clean approach, because it doesn't overload any existing fields ๐Ÿซง the downside is that it adds overhead to the packet because of the extra header. the added overhead is 8 octets. ๐Ÿ˜ญ BUT (okay, not capital BUT, sorry) the Context Tag is only needed when a locator other than the one used as the ULID is in the packet. packets where both the Source and Destination Address fields contain the ULIDs don't need a Context Tag, since the receiver doesn't need to rewrite anything. ๐Ÿ™Œ that means this approach cuts the overhead, because the extra header is only needed after a failure.

the other thing: this approach changes the available MTU for some packets, because packets that include the Extension header have an MTU that's 8 octets shorter. ๐Ÿฐ but path changes through the network can already give a different MTU anyway, so having a locator change (which means a path change) affect the MTU doesn't introduce any new issues. no new problems, periodt ๐Ÿ’–

D.3. Context-Loss Detection โœจ

okay bestie, this appendix is all about what happens when a shim context just... disappears ๐Ÿ’€ and how we deal with it ๐Ÿซถ The setup: Node A and Node B are chatting using IPA1 and IPB1. Later, a shim context gets set up between them, with IPA1 and IPB1 as the ULIDs and with IPA1,...,IPAn and IPB1,...,IPBm as the locator sets, respectively.

Then it can happen that one of the hosts (like Host A) loses the shim context later on ๐Ÿ˜ญ That could be because Host A has a more aggressive garbage collection policy than Host B, or because an error happened in the shim layer at Host A and wiped out the context state. Literally the worst.

The mechanisms in this appendix are here to save the day ๐Ÿฆ‹ There are basically two jobs to handle this: first, the context loss has to be detected, and second, the context needs to be recovered or re-established. Two steps, very doable, very main character ๐Ÿ’…

Mechanisms for detecting context loss.

These mechanisms are basically each end of the context periodically sending a packet with context-specific info to the other end. When a packet like that shows up, the receiver checks that the required context exists. If it doesn't, the receiver sends a packet back to tell the sender there's a problem ๐Ÿšจ

An obvious option would be a dedicated context keepalive exchange, where packets get sent periodically just for this purpose. This was considered and discarded because it seemed like overkill to define a whole new packet exchange just for this issue ๐Ÿ™„

Another option is to piggyback the context-loss detection onto other packet exchanges that already exist. In particular, both shim control packets and data packets can be used for this ๐Ÿงš

Shim control packets are the easy win here, because they already carry context-specific information. So when a node gets one, it checks whether the context exists. The catch is that shim control frequency may not be enough for context-loss detection, since control packet exchanges can be super limited for a session in certain scenarios ๐Ÿ˜ฌ

Data packets, on the other hand, are expected to show up way more often, but they don't necessarily carry context-specific information. For example, packets sent before a locator change (so, packets carrying the ULIDs in the address fields) don't need context info, since they don't need any shim processing. Packets that carry locators that differ from the ULIDs do carry context information.

Now here's the tea ๐Ÿ“ We have to make a distinction between the different approaches for carrying the Context Tag. Specifically, there's a difference between approaches where packets are explicitly marked as shim packets and approaches where they aren't. Say the Context Tag is carried in the Flow Label and packets aren't marked as shim packets (no new Next Header values are defined for shim). Then a receiver that has lost the associated context can't tell that the packet is tied to a missing context. The packet just gets passed unchanged to the upper-layer protocol, which will probably silently discard it because of a checksum error. The result? The context loss goes completely undetected ๐Ÿ’€ That's one more reason to ditch an approach that carries the Context Tag in the Flow Label without explicitly marking shim packets as such.

On the flip side, approaches that mark shim data packets (like ones using the Extension header, or the Flow Label with new Next Header values) let the receiver detect when the context for a received packet is missing. In that case, data packets double as a context-loss detection exchange too ๐Ÿ™Œ But only packets carrying a locator that differs from the ULID get marked. Which basically means context loss gets detected after an outage has already happened, meaning alternative locators are already being used. Oof.

To sum it up: the proposed context-loss detection mechanisms use shim control packets and Shim6 Payload Extension headers to detect context loss. Shim control packets can catch context loss for the whole lifetime of the context, but their expected frequency is very low in some cases. Shim6 Payload Extension headers usually show up way more often, but they only catch context loss after an outage. So it's going to be common that context loss gets detected after a failure, which means it's detected exactly when it's actually needed ๐Ÿ˜ฉ That's why a mechanism for recovering from context loss is required if this approach is used.

Overall, the detection mechanism works like this: the end that still has the context available sends a message referring to that context. When the message comes in, the end that lost the context spots the situation and notifies the other end about the context-loss event, by sending a packet containing the lost context information pulled from the received packet โœจ

One option is to just send an error message containing the received packets (or at least as much of the received packet as the MTU allows to fit). One goal of this notification is to let the other end, the one still holding context state, re-establish the lost context ๐ŸŽ€ The plain way to re-establish it is to perform the 4-way initial handshake. But that's a time-consuming exchange, and time is critical here, because we're re-establishing a context that's needed right now (context-loss detection may happen only after a failure). So the option used in this protocol is different: replace the error message with a modified R1 message, so the time needed for the context-establishment exchange gets reduced โšก When the end that still has the context state receives this modified R1 message, it can finish the context-establishment exchange and restore the lost context. Iconic recovery arc, honestly ๐Ÿ‘‘

D.4. Securing Locator Sets โœจ

okay so bestie, adopting something like SHIM, which lets a ULID get bound to a whole set of locators, opens the door to different kinds of redirection attacks, as described in [15] ๐Ÿ˜ฌ. The security goal for the shim protocol is not introducing any new vulnerability into the Internet architecture ๐Ÿ›ก๏ธ. Providing extra protection beyond what the single-homed IPv6 Internet already has is explicitly a non-goal ๐Ÿ™…โ€โ™€๏ธ.

Several security mechanisms were considered to protect the shim protocol. We'll walk through some of them here ๐ŸŽ€.

The simplest option is cookies: a randomly generated bit string negotiated during the context-establishment phase and then included in later signaling messages ๐Ÿช. This lets you check that the party who did the initial handshake is the same party now introducing new locators. Before a new locator gets used, there's also an exchange through that new locator, which verifies that whoever is sitting at the new locator knows the cookie. In other words, it's the same party from the initial handshake ๐Ÿซถ.

Honestly this gives a fair amount of protection, but it leaves the door open for so-called time-shifted attacks ๐Ÿ˜ญ. Here's the tea: an attacker on the path sniffs the cookie out of any signaling message, then leaves the path and still pulls off a redirection attack. Since they have the cookie, they can add a new locator to the locator set and also pass the reachability exchange, as long as they can receive packets at that new locator ๐Ÿ’€. Compare that to today's single-homed IPv6 situation, where the attacker has to stay on-path for the entire lifetime of the attack. With cookie-only protection, someone who was on the path once can keep attacking after they've left ๐Ÿ‘ป.

It gets worse, ngl ๐Ÿ™ˆ. Because the cookie rides along in signaling messages, an attacker can grab it from any one of them, which leaves the protocol vulnerable for the whole lifetime of the shim context ๐Ÿ˜ฉ. A possible upgrade is a shared secret: a bit string negotiated during the initial handshake and then used as a key to protect the messages that follow ๐Ÿ”. With this trick the attacker has to be on the path and sniffing during the initial handshake, since that's the only moment the shared secret gets exchanged. That's a much more specific moment to catch them, and it does improve security, but this approach is still vulnerable to time-shifted attacks ๐Ÿ˜ค. It's also worth noting that, depending on protocol details, an attacker might be able to force the initial handshake to happen again, for example by blocking messages so the parties think the context was lost. So the end result might not be that different from the cookie-based approach ๐Ÿ™ƒ.

Another option discussed while designing this protocol was using IPsec to protect the shim protocol ๐Ÿง. The real puzzle here is how to securely bind an address that's being used as a ULID to a locator set that can be used to exchange packets. IPsec's way of securely binding an address to cryptographic keys is digital certificates ๐Ÿ“œ. That means an IPsec-based solution would need a common, mutually trusted third party to generate digital certificates binding the key and the ULID. Since the shim protocol is meant to work globally, that would basically mean a global public key infrastructure (PKI) ๐ŸŒ. The big issue with this route is the deployment difficulties that come with a global PKI ๐Ÿ˜ตโ€๐Ÿ’ซ.

The other possibility would be opportunistic IPsec, like Better-Than-Nothing-Security (BTNS) [22] ๐Ÿคทโ€โ™€๏ธ. Still, this has its own problems. The approach requires a leap-of-faith to bind a given address to the public key being used. That would actually block the most critical security feature a Shim6 security solution needs, which is proving identifier ownership ๐Ÿšซ. On top of all that, using IPsec would mean turning on per-packet AH/ESP just for multihoming to happen, which is a lot of overhead for one feature ๐Ÿ˜ฎโ€๐Ÿ’จ.

In general, SHIM6 was expected to work between pairs of hosts that have no prior arrangement, no security association, and no common trusted third party ๐ŸŒธ. It was also seen as undesirable to have to turn on per-packet AH/ESP just for multihoming to occur. Still, Shim6 should work, and it should offer an additional level of security where two hosts choose to use IPsec ๐ŸŽ.

Another design alternative would have used some form of opportunistic or Better-Than-Nothing Security (BTNS) IPsec to handle these tasks with IPsec instead ๐Ÿ”„. Basically, HIP in opportunistic mode is very similar to SHIM6, except HIP uses IPsec, employs per-packet ESP, and introduces another set of identifiers. So, it's giving "same vibe, different outfit" ๐Ÿ‘—.

Finally, two technologies were selected to protect the shim protocol: HBA [3] and CGA [2] ๐Ÿ‘‘. They provide a similar level of protection, but they offer different functionality with different computational costs ๐Ÿ’….

The HBA mechanism relies on being able to generate all of a multihomed host's addresses as an unalterable set of intrinsically bound IPv6 addresses, known as an HBA set ๐Ÿงฉ. Here's the trick: addresses include a cryptographic one-way hash of the prefix set in the interface identifier part. So the binding between all the available addresses is encoded inside the addresses themselves, which provides hijacking protection ๐Ÿ”’. Any peer running the shim protocol can efficiently verify that the alternative addresses proposed for continuing the communication are bound to the initial address with a simple hash calculation ๐Ÿงฎ. The catch is that once an HBA set is generated, it's fixed and can't be changed without also changing all the addresses in the set. In other words, HBA doesn't support dynamically adding an address to a previously generated HBA set ๐Ÿ˜ฌ. The upside is that verifying a locator set only takes hash operations, so the computational cost is super low ๐Ÿฆ‹.

In a CGA-based approach, the address used as the ULID is a CGA that contains a hash of a public key in its interface identifier ๐Ÿ”‘. The result is a secure binding between the ULID and the associated key pair. That lets each peer use the matching private key to sign the shim messages that carry locator set information โœ๏ธ. The trust chain goes like this: the ULID used for the communication is securely bound to the key pair because it contains the hash of the public key, and the locator set is bound to the public key through the signature ๐Ÿ”—. CGA can support dynamic addition of new locators to the locator set, because the node only needs to sign the new locator with the private key associated with the CGA used as the ULID ๐Ÿ™Œ. The limitation is that it requires systematic use of public key cryptography, and that comes with its associated computational cost ๐Ÿฅฒ.

Either HBA or CGA provides time-shifted attack protection, since the ULID is securely bound to a locator set that can only be defined by the owner of the ULID ๐Ÿ›ก๏ธโœจ.

So the design decision was that both HBA and CGA are supported ๐Ÿ’–. That way, when only stable address sets are needed, nodes can enjoy the low computational cost of HBA. When dynamic locator sets are needed, that can be done through CGAs, with the extra cost that comes with it ๐Ÿ’œ. Plus, because HBAs are defined as a CGA extension, the addresses available on a node can be CGAs and HBAs at the same time. That means you can use HBA or CGA functionality when you need it, without changing the addresses you're using ๐Ÿงš.


D.5. ULID-Pair Context-Establishment Exchange ๐ŸŒˆ

Two options were considered for the ULID-pair context-establishment exchange: a 2-way handshake and a 4-way handshake ๐Ÿค”.

A key goal for this exchange was protection against DoS attacks ๐Ÿšจ. The attack under consideration was basically an attacker launching a huge amount of ULID-pair establishment-request packets, which exhausts the victim's resources, kind of like TCP SYN flooding ๐Ÿ’€.

A 4-way handshake protects against these attacks because the receiver doesn't create any state for a given context until it receives the second packet, which carries prior-contact proof in the form of a token ๐ŸŽŸ๏ธ. At that point, the receiver can verify that at least the address used by the initiator is valid to some extent, since the initiator is able to receive packets at this address ๐Ÿ“ฌ. In the worst case, the responder can track down the attacker using this address ๐Ÿ•ต๏ธโ€โ™€๏ธ. The drawback is that it imposes a 4-packet exchange for any context establishment ๐Ÿ˜ฉ. That would be a big deal if the shim context had to be established up front, before communication could proceed. But thanks to the deferred context-establishment capability of the shim protocol, this limitation has a reduced impact on performance ๐Ÿ™Œ. (However, it may have a greater impact in the situation of context recovery, as discussed earlier. However, in this case, it is possible to perform optimizations to reduce the number of packets as described above.) ๐Ÿง

The other option considered was a 2-way handshake with the possibility of falling back to a 4-way handshake in case of attack โšก. In this approach, the ULID-pair establishment exchange normally consists of a 2-packet exchange, and it doesn't verify that the initiator has performed prior contact before creating context state ๐Ÿƒโ€โ™€๏ธ. If a DoS attack is detected, the responder falls back to a 4-way handshake similar to the one described above, to stop the detected attack from proceeding ๐Ÿ›‘. The main difficulty is figuring out how to detect that a responder is currently under attack ๐Ÿฅบ. Also, because this is a 2-way exchange, it's not possible to use the number of half-open sessions (like TCP does) to detect an ongoing attack. Different heuristics would need to be considered instead ๐Ÿ”.

The design decision was that, given the current impact of DoS attacks and the low impact of the 4-way exchange in the shim protocol (thanks to deferred context establishment), a 4-way exchange would be adopted for the base protocol ๐Ÿ‘‘๐Ÿ’–.

D.6. Updating Locator Sets ๐Ÿฆ‹

Okay so there are two ways to handle adding and removing locators ๐Ÿซถ. The atomic approach sends the complete locator set every single time it changes, no shortcuts ๐Ÿ“ฆ. The differential approach only sends the differences between the existing locator set and the new one โœจ. Atomic has more overhead bc the whole locator set gets exchanged each time ๐Ÿ˜ญ. Differential needs re-synchronization of both ends through changes, which means both ends have to agree on what the current locator set actually is ๐Ÿ™ˆ Ngl that synchronization requirement is a whole mood ๐Ÿ’€.

Because of those synchronization difficulties, the atomic approach was selected ๐Ÿ‘‘.


D.7. State Cleanup ๐Ÿงน

Okay so there are basically two ways to throw away existing state about a correspondent node's locators, keys, and identifiers ๐Ÿ—‘๏ธ: a coordinated approach and a unilateral approach ๐Ÿ’….

In the unilateral approach, each node discards information about the other node without coordinating with it, based on some local timers and heuristics โฒ๏ธ. No packet exchange is needed for this ๐Ÿฆ‹. But now it's possible that one node has already tossed the state while the other one still hasn't ๐Ÿ˜ฌ. In that case, a No Context Error message may be required to let the other node know what's going on, and a recovery mechanism might also be needed ๐Ÿš‘.

A coordinated approach would use an explicit CLOSE mechanism, kinda like the one specified in HIP [20] ๐Ÿค. If there's an explicit CLOSE handshake plus an associated timer, then there's no longer a need for the No Context Error message due to a peer having garbage collected its end of the context ๐Ÿงผ. BUT there's still potentially a need for a No Context Error message if a peer loses its whole state (aka it crashes and then reboots) ๐Ÿ’ฅ. The only way we can completely do away with the No Context Error message is if we assume the reboot takes at least as long as the CLOSE timer, or if it's totally fine to not provide complete service until CLOSE-timer minutes after the crash ๐Ÿ•ฐ๏ธ.

Now here's the spicy part: the context confusion issue ๐ŸŒถ๏ธ. Using a unilateral approach to discard context state clearly opens the door to context confusion, where one end unilaterally discards the context state while the other end doesn't ๐Ÿšช. The end that discarded the state can then re-use the Context Tag value it used for that state for a different context, and boom, potential confusion ๐Ÿ’ซ. To show where things can go wrong, let's look at this scenario:

  • Hosts A and B establish context 1 using CTA and CTB as Context Tags ๐Ÿค.
  • Later on, A discards context 1, and the Context Tag value CTA becomes available for reuse โ™ป๏ธ.
  • However, B still keeps context 1 ๐Ÿ˜ณ.

This would create context confusion in the following two cases:

  • A new context 2 is established between A and B with a different ULID pair (or Forked Instance Identifier), and A uses CTA as the Context Tag. If the locator sets used for both contexts are not disjoint, we have context confusion ๐Ÿ™ƒ.
  • A new context is established between A and C, and A uses CTA as the Context Tag value for this new context. Later on, B sends a Payload Extension header and/or control messages containing CTA, which could be interpreted by A as belonging to context 2 (if no proper care is taken). Again, context confusion ๐Ÿ˜ตโ€๐Ÿ’ซ.

Someone might think a coordinated approach would get rid of all this confusion and make the protocol way simpler ๐Ÿค”. Not so fast ๐Ÿ™…โ€โ™€๏ธ. Even with a coordinated approach using a CLOSE/CLOSE ACK exchange, a host can still reboot before it has time to do the CLOSE exchange ๐Ÿ”„. So the coordinated approach does kill context confusion caused by premature garbage collection, but it doesn't prevent the same situations from happening because one of the involved hosts crashed and rebooted ๐Ÿฅฒ. Bottom line: even if we went coordinated, we'd still need to deal with context confusion and provide ways to detect it and recover from it ๐Ÿ›Ÿโœจ.


Authors' Addresses ๐ŸŽ€

Erik Nordmark
Sun Microsystems
17 Network Circle
Menlo Park, CA 94025
USA

Phone: +1 650 786 2921
EMail: erik.nordmark@sun.com


Marcelo Bagnulo
Universidad Carlos III de Madrid
Av. Universidad 30
Leganes, Madrid  28911
SPAIN

Phone: +34 91 6248814
EMail: marcelo@it.uc3m.es
URI:   http://www.it.uc3m.es

And that's the whole RFC, bestie ๐ŸŒˆ๐Ÿ’–๐Ÿซถ

๐Ÿ“ฆ where this page comes from