RFC 8156

DHCPv6 Failover Protocol

๐Ÿ“… published June 2017, from ietf

RFC 8156: DHCPv6 Failover Protocol ๐ŸŽ€ (part 1 of 20)

okay so bestie, this is RFC 8156, and its title is DHCPv6 Failover Protocol ๐Ÿ’– It's a Standards Track doc, which means it's the real deal and not an experiment ๐Ÿ’… It came out in June 2017 and was written by T. Mrugalski from ISC and K. Kinnear from Cisco. It's part of the IETF stream and has ISSN 2070-1721. The title block doesn't list anything it obsoletes or updates, so there's no drama there ๐Ÿ™ˆ


Abstract โœจ

okay so DHCPv6, as defined in "Dynamic Host Configuration Protocol for IPv6 (DHCPv6)" (RFC 3315), does not offer server redundancy ๐Ÿ˜ญ this doc defines a protocol implementation to provide DHCPv6 failover, which is a mechanism for running two servers where either one can take over clients' leases if the other has a server failure or a network partition ๐Ÿซถ it meets the requirements for DHCPv6 failover detailed in "DHCPv6 Failover Requirements" (RFC 7031) and it's giving reliability, no cap ๐Ÿ”ฅ


Status of This Memo ๐Ÿ“œ

this is an Internet Standards Track document, so it's official ๐Ÿ‘‘

this doc is a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community. it got public review and was approved for publication by the Internet Engineering Steering Group (IESG). if you want more info on Internet Standards, check out Section 2 of RFC 7841 ๐Ÿฆ‹

for the current status, any errata, and how to give feedback, go to http://www.rfc-editor.org/info/rfc8156 ๐Ÿ’œ


Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved. โœจ

this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stood on the publication date. please actually read these, because they describe your rights and restrictions for this doc ๐Ÿ™ˆ one important bit: code components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as described in the Simplified BSD License ๐Ÿ’–


Table of Contents ๐Ÿงš

1. Introduction ....................................................5
2. Requirements Language ...........................................5
3. Glossary ........................................................6
4. Failover Concepts and Mechanisms ...............................10
   4.1. Required Server Configuration .............................10
   4.2. IPv6 Address and Delegable Prefix Allocation ..............10
        4.2.1. Independent Allocation .............................10
               4.2.1.1. Independent Allocation Algorithm ..........11
        4.2.2. Proportional Allocation ............................11
               4.2.2.1. Reallocating Leases .......................13
   4.3. Lazy Updates ..............................................14
   4.4. Maximum Client Lead Time (MCLT) ...........................14
        4.4.1. MCLT Example .......................................16
5. Message and Option Definitions .................................19
   5.1. Message Framing for TCP ...................................19
   5.2. Failover Message Format ...................................19
   5.3. Messages ..................................................20
        5.3.1. BNDUPD .............................................20
        5.3.2. BNDREPLY ...........................................20
        5.3.3. POOLREQ ............................................20
        5.3.4. POOLRESP ...........................................21
        5.3.5. UPDREQ .............................................21
        5.3.6. UPDREQALL ..........................................21
        5.3.7. UPDDONE ............................................21
        5.3.8. CONNECT ............................................21
        5.3.9. CONNECTREPLY .......................................22
        5.3.10. DISCONNECT ........................................22
        5.3.11. STATE .............................................22
        5.3.12. CONTACT ...........................................22
   5.4. Transaction-id ............................................22
   5.5. Options ...................................................23
        5.5.1. OPTION_F_BINDING_STATUS ............................23
        5.5.2. OPTION_F_CONNECT_FLAGS .............................24
        5.5.3. OPTION_F_DNS_REMOVAL_INFO ..........................25
               5.5.3.1. OPTION_F_DNS_HOST_NAME ....................26
               5.5.3.2. OPTION_F_DNS_ZONE_NAME ....................26
               5.5.3.3. OPTION_F_DNS_FLAGS ........................27
        5.5.4. OPTION_F_EXPIRATION_TIME ...........................28
        5.5.5. OPTION_F_MAX_UNACKED_BNDUPD ........................29
        5.5.6. OPTION_F_MCLT ......................................29
        5.5.7. OPTION_F_PARTNER_LIFETIME ..........................30
        5.5.8. OPTION_F_PARTNER_LIFETIME_SENT .....................30
        5.5.9. OPTION_F_PARTNER_DOWN_TIME .........................31
        5.5.10. OPTION_F_PARTNER_RAW_CLT_TIME .....................32
        5.5.11. OPTION_F_PROTOCOL_VERSION .........................32
        5.5.12. OPTION_F_KEEPALIVE_TIME ...........................33
        5.5.13. OPTION_F_RECONFIGURE_DATA .........................34
        5.5.14. OPTION_F_RELATIONSHIP_NAME ........................35
        5.5.15. OPTION_F_SERVER_FLAGS .............................36
        5.5.16. OPTION_F_SERVER_STATE .............................37
        5.5.17. OPTION_F_START_TIME_OF_STATE ......................38
        5.5.18. OPTION_F_STATE_EXPIRATION_TIME ....................38
   5.6. Status Codes ..............................................39
6. Connection Management ..........................................40
   6.1. Creating Connections ......................................40
        6.1.1. Sending a CONNECT Message ..........................41
        6.1.2. Receiving a CONNECT Message ........................42
        6.1.3. Receiving a CONNECTREPLY Message ...................43
   6.2. Endpoint Identification ...................................44
   6.3. Sending a STATE Message ...................................45
   6.4. Receiving a STATE Message .................................46
   6.5. Connection Maintenance Parameters .........................46
   6.6. Unreachability Detection ..................................47
7. Binding Updates and Acks .......................................47
   7.1. Time Skew .................................................47
   7.2. Information Model .........................................48
   7.3. Times Required for Exchanging Binding Updates .............52
   7.4. Sending Binding Updates ...................................53
   7.5. Receiving Binding Updates .................................56
        7.5.1. Monitoring Time Skew ...............................56
        7.5.2. Acknowledging Reception ............................56
        7.5.3. Processing Binding Updates .........................57
        7.5.4. Accept or Reject? ..................................57
        7.5.5. Accepting Updates ..................................59
   7.6. Sending Binding Replies ...................................61
   7.7. Receiving Binding Acks ....................................63
   7.8. BNDUPD/BNDREPLY Data Flow .................................65
8. Endpoint States ................................................66
   8.1. State Machine Operation ...................................66
   8.2. State Machine Initialization ..............................69
   8.3. STARTUP State .............................................70
        8.3.1. Operation in STARTUP State .........................70
        8.3.2. Transition out of STARTUP State ....................70
   8.4. PARTNER-DOWN State ........................................72
        8.4.1. Operation in PARTNER-DOWN State ....................72
        8.4.2. Transition out of PARTNER-DOWN State ...............73
   8.5. RECOVER State .............................................74
        8.5.1. Operation in RECOVER State .........................74
        8.5.2. Transition out of RECOVER State ....................74
   8.6. RECOVER-WAIT State ........................................76
        8.6.1. Operation in RECOVER-WAIT State ....................76
        8.6.2. Transition out of RECOVER-WAIT State ...............76

   8.7. RECOVER-DONE State ........................................77
        8.7.1. Operation in RECOVER-DONE State ....................77
        8.7.2. Transition out of RECOVER-DONE State ...............77
   8.8. NORMAL State ..............................................77
        8.8.1. Operation in NORMAL State ..........................78
        8.8.2. Transition out of NORMAL State .....................78
   8.9. COMMUNICATIONS-INTERRUPTED State ..........................79
        8.9.1. Operation in COMMUNICATIONS-INTERRUPTED State ......80
        8.9.2. Transition out of COMMUNICATIONS-INTERRUPTED
               State ..............................................80
   8.10. POTENTIAL-CONFLICT State .................................82
         8.10.1. Operation in POTENTIAL-CONFLICT State .............82
         8.10.2. Transition out of POTENTIAL-CONFLICT State ........82
   8.11. RESOLUTION-INTERRUPTED State .............................83
         8.11.1. Operation in RESOLUTION-INTERRUPTED State .........84
         8.11.2. Transition out of RESOLUTION-INTERRUPTED State ....84
   8.12. CONFLICT-DONE State ......................................84
         8.12.1. Operation in CONFLICT-DONE State ..................85
         8.12.2. Transition out of CONFLICT-DONE State .............85
9. DNS Update Considerations ......................................85
   9.1. Relationship between Failover and DNS Update ..............86
   9.2. Exchanging DNS Update Information .........................87
   9.3. Adding RRs to the DNS .....................................89
   9.4. Deleting RRs from the DNS .................................90
   9.5. Name Assignment with No Update of DNS .....................91
10. Security Considerations .......................................91
11. IANA Considerations ...........................................92
12. References ....................................................94
   12.1. Normative References .....................................94
   12.2. Informative References ...................................96
Acknowledgements ..................................................96
Authors' Addresses ................................................96

1. Introduction โœจ

okay so this doc defines a DHCPv6 failover protocol ๐Ÿฆ‹ which is basically a way for two DHCPv6 servers [RFC3315] to team up, so either one can take over clients' leases if the other server goes down or the network gets split ๐Ÿซถ if you want the big-picture tea on DHCPv6 failover (the problems, use cases, benefits and shortcomings) go read [RFC7031] ๐Ÿ“š

the failover protocol lets cooperating DHCP servers work together to give clients a service that's way more available than a single server could manage alone ๐Ÿ’ช it's built to protect DHCP clients against server unreachability, including server failure and network partition ๐Ÿ›ก๏ธ it's even possible to deploy exactly two servers that keep providing a lease for an IPv6 address [RFC3315] or on an IPv6 prefix [RFC3633], so the client never experiences lease expiration or gets reassigned to a different IPv6 address or prefix when one of the two servers fails ๐ŸŽ€

the failover protocol defines an active-passive mode, sometimes called a "hot standby" model ๐Ÿ”ฅ so during normal operation one server is active (it actively responds to clients' requests) while the second is passive (it receives clients' requests but only responds to the ones specifically directed to it) ๐Ÿ™ˆ the secondary keeps a copy of the binding database and is ready to take over all incoming queries if the primary server fails ๐Ÿ’œ

the failover protocol is designed to provide lease stability for leases with valid lifetimes beyond a short period ๐ŸŒธ

โš ๏ธ the DHCPv6 failover protocol MUST NOT be used for new leases shorter than 30 seconds. leases reaching the end of their lifetimes are not affected by this restriction.

the failover protocol fulfills all DHCPv6 failover requirements defined in [RFC7031] โœ…


2. Requirements Language

okay this is the important bit ๐Ÿง the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐Ÿ’…


3. Glossary ๐Ÿ“–

this is a supplemental glossary that should be used together with the definitions in Section 2 of RFC 7031 [RFC7031] ๐Ÿงš

  • Absolute Time ๐Ÿ•ฐ๏ธ "Absolute time" refers to the time in seconds since midnight January 1, 2000 UTC, modulo 2^32.
  • Address Lease ๐Ÿ  "Address lease" refers to a lease involving an IPv6 address. it's typically used when you need to tell the lease for an IPv6 address apart from a lease for a DHCP prefix. see the definitions for "delegated prefix" and "prefix lease" below.
  • auto-partner-down ๐Ÿค– "auto-partner-down" refers to a capability where a failover server moves from COMMUNICATIONS-INTERRUPTED state to PARTNER-DOWN state automatically, without operator intervention.
  • Available (Lease or Prefix) ๐Ÿ’š a lease or delegable prefix is available if it could be allocated for use by a DHCP client. it's available on the main server when it's in the FREE state, and available on the secondary server when it's in the FREE-BACKUP state. the term "available" is sometimes used when it would be awkward to say "FREE on the primary server and FREE-BACKUP on the secondary server" ๐Ÿ˜…
  • Binding-Status ๐ŸŽซ a lease can hold a variety of states (see Section 5.5.1 for a list). these are also referred to as the "binding-status" of the lease.
  • Delegable Prefix ๐ŸŒฟ "Delegable prefix" refers to a prefix from which other prefixes may be delegated, using the mechanisms described in [RFC3633]. a prefix that has been delegated is known as a "delegated prefix" or a "prefix lease".
  • Delegated Prefix ๐ŸŽ a delegated prefix is a prefix that has been delegated to a DHCP client as described in [RFC3633]. depending on the context, a delegated prefix may also be described as a "prefix lease" when it's necessary to tell it apart from an "address lease".
  • DHCP Prefix ๐Ÿ—บ๏ธ a DHCP prefix is part of the IPv6 address space configured to be managed by a DHCP server.
  • Failover Endpoint ๐Ÿ”Œ the failover protocol permits a unique failover "endpoint" for each failover relationship a failover server participates in. the failover relationship is defined by a relationship name and includes:
    • the failover partner IP address,
    • the role this server takes with respect to that partner (primary or secondary), and
    • the prefixes from which addresses can be leased, as well as prefixes from which other prefixes can be delegated (delegable prefixes), that are associated with that relationship.

the failover endpoint can take actions and hold unique states. typically there's one failover endpoint per partner (server), although there may be more ๐Ÿ‘‘

  • Failover Communication ๐Ÿ’ฌ "Failover communication" refers to all messages exchanged between partners.
  • Independent Allocation ๐Ÿฐ "Independent allocation" refers to an allocation algorithm that splits the available pool of address leases between the primary and secondary servers. it's used for IPv6 address allocations. see Section 4.2.1.
  • Lease ๐ŸŽ€ a lease is an association of a DHCP client with an IPv6 address or delegated prefix. this might refer to either an existing association or a potential one.
  • MCLT (Maximum Client Lead Time) โณ the fundamental relationship that much of the correctness of the failover protocol depends on is that the lease expiration time known to a DHCP client MUST NOT be greater by more than the MCLT beyond the later of the partner lifetime acknowledged by that server's failover partner or the current time (i.e., now). see Section 4.4.
  • Partner ๐Ÿค the other DHCP server that participates in a failover relationship is referred to as the "partner". when the role (primary or secondary) isn't important, the other server is referred to as a "failover partner" or sometimes simply "partner".
  • Prefix Lease ๐ŸŒˆ a prefix lease is a lease involving a prefix that is delegated or could be delegated, as opposed to a lease for a single IPv6 address. a prefix lease can also be described as a "delegated prefix".
  • Primary Server ๐Ÿฅ‡ the primary server is the first of the two DHCP servers that participate in a failover relationship. when both servers are operating, this server handles most of the client traffic. its failover partner is referred to as the "secondary server".
  • Proportional Allocation ๐Ÿฅง "Proportional allocation" is an allocation algorithm that splits the delegable prefixes between the primary and secondary servers, and maintains a more or less fixed proportion of the delegable prefixes between both servers. see Section 4.2.2.
  • Renew Responsive ๐Ÿ” a server that is "renew responsive" will respond to valid DHCP client messages directed to it by having an OPTION_SERVERID option in the message that contains the DHCP Unique Identifier (DUID) of the renew responsive server. see [RFC3315].
  • Responsive ๐Ÿ™‹ a server that is responsive will respond to all valid DHCP client messages.
  • Secondary Server ๐Ÿฅˆ the secondary server is the second of the two DHCP servers that participate in a failover relationship. its failover partner is referred to as the "primary server" (as defined above). when both servers are operating, this server (the secondary) typically doesn't handle client traffic and acts as a backup to the primary server. however, it will respond to RENEW requests directed specifically to it ๐Ÿ’–
  • Server ๐Ÿ–ฅ๏ธ "Server" refers to a DHCP server that implements DHCPv6 failover. "Server" and "failover endpoint" are synonymous only if the server participates in only one failover relationship.
  • State ๐Ÿ“ the term "state" is used in two ways in this document. a failover endpoint is always in some state, and there's a series of states that a failover endpoint can move through. see Section 8 for details of the failover endpoint states. a lease also has a state, and this is sometimes referred to as a "binding-status". see Section 5.5.1 for a list of the states a lease can hold.
  • Unresponsive ๐Ÿ™ˆ a server that is unresponsive will not respond to DHCP client messages.

4. Failover Concepts and Mechanisms ๐Ÿงฉ

the following concepts and mechanisms are necessary for the failover protocol to operate. they aren't currently used by DHCPv6 [RFC3315]. the failover protocol supports all of these concepts and mechanisms โœจ

4.1. Required Server Configuration

servers frequently have several kinds of leases available on a particular network segment. the failover protocol assumes that both the primary server and the secondary server are configured identically with regard to the prefixes and links involved in DHCP. for delegable prefixes (involved in proportional allocation), the primary server is responsible for allocating the secondary server the correct proportion of the available delegable prefixes. IPv6 addresses (involved in independent allocation) are allocated to the primary and secondary servers algorithmically, so they don't need an explicit message transfer to be distributed ๐Ÿ™Œ

4.2. IPv6 Address and Delegable Prefix Allocation

okay so there are currently two allocation algorithms defined: one for address leases and one for prefix leases ๐Ÿ“

4.2.1. Independent Allocation โœจ

okay so in this scheme, which is for handing out individual IPv6 addresses ๐Ÿฆ‹, the available addresses get split between the servers permanently (until the server config changes ๐Ÿ’…). The split happens as part of the initial connection setup between the primary and secondary servers. Once each server has its addresses, nobody has to reassign anything, ever ๐Ÿ™Œ. The algorithm is algorithmic, so each server can tell which addresses are its own without a message exchange for every address ๐Ÿง . It's simpler than proportional allocation because there's no rebalancing mechanism to deal with ๐Ÿ’–. It does assume that each server's pool will never run out, which, sis, is a big assumption ๐Ÿ‘€.

Once each server has its pool from the initial connection setup, it can hand those addresses out to clients ๐ŸŽ€. When a client releases a lease, or the lease just expires, the address goes back into the pool of whichever server leased it ๐ŸŒธ. A lease can be renewed by a responsive server or by a renew responsive server ๐Ÿซถ. When an IPv6 address goes PENDING-FREE (see Section 7.2), it belongs to whichever server the independent allocation algorithm assigned it to โญ.

Heads up: IPv6 addresses using the independent allocation approach are ignored when a server processes a POOLREQ message ๐Ÿ’€.

During COMMUNICATIONS-INTERRUPTED events, a partner MAY keep extending existing address leases when clients ask for it ๐ŸŒˆ. An operational partner MUST NOT lease addresses that were assigned to its downed partner and later expired, or that a client released or declined ๐Ÿšซ. When it's in PARTNER-DOWN state, a server MUST allocate new leases from its own pool ๐Ÿ“. It MUST NOT touch its partner's pool to allocate new leases. Not even a little bit ๐Ÿ™…โ€โ™€๏ธ.

4.2.1.1. Independent Allocation Algorithm ๐Ÿงฎ

Okay, the actual rule: for each address that can be allocated, the primary server MUST only allocate IPv6 addresses whose low-order bit (aka bit 127) is equal to 1 ๐Ÿ’œ. The secondary server MUST only allocate IPv6 addresses whose low-order bit (aka bit 127) is equal to 0 ๐Ÿฆ‹. Odd addresses go to the primary, even addresses go to the secondary, and that's the whole vibe ๐Ÿ’….

4.2.2. Proportional Allocation ๐ŸŒธ

In this scheme, each server has its own pool of prefixes it can delegate, called "delegable prefixes" ๐Ÿงš. Those can be prefixes that other prefixes can be delegated from, or prefixes that are the right size for delegation but aren't currently handed to any client ๐ŸŽ€. The remaining delegable prefixes get split between the primary and secondary servers in a configured proportion โญ. Here's the important tea: a delegated prefix (also known as a "prefix lease") is NOT owned by any particular server ๐Ÿ™ˆ. Only an available delegable prefix is owned by a server. Once it's delegated (leased) to a client, it turns into a prefix lease and neither failover partner owns it ๐Ÿ’€. When it becomes available again, the primary server owns it first, and then it might or might not get allocated to the secondary by the primary ๐Ÿซถ.

Here's the flow of a delegable prefix ๐Ÿฆ‹. At the start, it's part of a set of delegable prefixes, and the primary owns all of them. A delegable prefix can be allocated to the secondary, and then the secondary owns it ๐Ÿ’œ. Either server can allocate and delegate prefixes from the delegable prefixes it owns ๐Ÿ’…. Once those prefixes are delegated (leased) to clients, the servers stop owning them, and the clients they went to own them instead ๐ŸŒˆ. When the client releases the prefix or the lease expires, the prefix becomes available again, becomes a delegable prefix again, and goes back to being owned by the primary ๐Ÿ”ฅ.

A server only delegates prefixes out of its own pool of delegable prefixes in every state except PARTNER-DOWN ๐Ÿ“. In PARTNER-DOWN state, the operational partner can delegate prefixes from either pool, both its own and its partner's (once some time constraints have passed) ๐Ÿ‘‘. The operational partner SHOULD allocate from its own pool before it touches its partner's pool ๐Ÿซถ. Balancing and maintaining these pools is a big deal, because the goal is to keep a more or less constant ratio of delegable prefixes between the two servers ๐Ÿ’–.

Each server knows which delegable prefixes are in its own pool and which are in its partner's pool ๐Ÿง . That way it can allocate from its partner's pool without talking to its partner, if it ever has to ๐ŸŒธ.

The first time the servers integrate, the primary gives the secondary its initial batch of delegable prefixes. That kicks off when the secondary sends a POOLREQ message to the primary ๐ŸŽ€. At some point after, the primary replies with a POOLRESP message to say it got and processed the POOLREQ โœจ. The primary sends the allocated delegable prefixes to the secondary as prefix leases using BNDUPD messages ๐Ÿฆ‹. The POOLRESP can be sent before, during, or at the end of the BNDUPD exchanges that the POOLREQ set off ๐Ÿ™Œ. The POOLREQ/POOLRESP exchange also tells the primary to scan its database and make sure the secondary has enough delegable prefixes, based on some configured ratio ๐Ÿ”ฅ.

Delegable prefixes go to the secondary as prefix leases, using a BNDUPD message with an OPTION_IAPREFIX in the FREE-BACKUP state ๐Ÿ’œ. That state means the prefix lease is now available for the secondary to allocate ๐Ÿ“. Once the message is sent, the primary MUST NOT use those prefixes to allocate to DHCP clients, except when the server is in PARTNER-DOWN state ๐Ÿšซ.

The POOLREQ/POOLRESP exchange that the secondary starts is valid any time both partners are in contact ๐ŸŒˆ. Whenever the primary gets a POOLREQ, it SHOULD scan its database of delegable prefixes and figure out whether the secondary needs more delegable prefixes from the ones the primary currently owns ๐Ÿซถ.

To keep the leases balanced in a pretty dynamic way between the failover partners, the primary has some extra work to do ๐Ÿงš. It has to make sure the secondary has as many delegable prefixes as it needs, but not more than it needs โญ.

The primary SHOULD check the balance of delegable prefixes between itself and the secondary for a particular prefix whenever the number of possibly delegable prefixes for either server changes by more than a predetermined amount ๐Ÿ’…. Usually this doesn't mean counting existing delegable prefixes. It means working out how many prefixes could be delegated, based on the address ranges of the delegable prefixes each server has ๐Ÿงฎ. The primary SHOULD adjust the balance as needed to hit the configured delegable prefix balance, but it SHOULD use some threshold mechanism for those adjustments so it doesn't spend a ton of overhead maintaining the balance ๐ŸŒธ.

Whenever it wants, the primary can send an available delegable prefix to the secondary using a BNDUPD message in the FREE-BACKUP state ๐ŸŽ€. It can also try to take an available delegable prefix back from the secondary by sending a BNDUPD message in the FREE state ๐Ÿ‘€. If the secondary accepts that BNDUPD, the lease is now available to the primary and no longer available to the secondary ๐Ÿ’œ. Of course, the secondary MUST reject that BNDUPD message if it has already allocated that lease to a DHCP client ๐Ÿ™…โ€โ™€๏ธ.

4.2.2.1. Reallocating Leases ๐Ÿ”

When a server is in PARTNER-DOWN state, there's a waiting period before a delegated prefix can be reallocated to another client โณ. For delegable prefixes that are "available" when the server enters PARTNER-DOWN state, the wait is the MCLT counted from when it entered PARTNER-DOWN state ๐Ÿฆ‹. For delegated prefixes that are NOT available when the server enters PARTNER-DOWN state, the wait is the MCLT counted from the latest of these times: the acked-partner-lifetime, the partner-lifetime (if there is one), the expiration-time, or the time it entered PARTNER-DOWN ๐ŸŒˆ.

In any other state, a server can't reallocate a delegated prefix from one client to another without first telling its partner (through a BNDUPD message) and getting an acknowledgement (through a BNDREPLY message) that the partner knows the first client isn't using the lease ๐Ÿซถ. That's a lot of checking, but it keeps everyone honest ๐Ÿ’….

So an "available" delegable prefix on a server can be given to any client ๐ŸŽ€. A prefix that was delegated (leased) to a client and then expired, or was released by that client, moves to a new state: EXPIRED or RELEASED, respectively โœจ. The partner server then gets told that the delegated prefix was EXPIRED or RELEASED through a BNDUPD message ๐Ÿ™Œ. When the sending server gets the BNDREPLY for that prefix showing it's FREE, it moves the lease from EXPIRED or RELEASED to FREE, and the primary server can then allocate it to any clients ๐Ÿ”ฅ.

A server MAY reallocate a delegated prefix in the EXPIRED or RELEASED state to the same client with no restrictions, as long as it hasn't sent a BNDUPD message about that prefix to its partner ๐Ÿ’œ. That could happen if the prefix lease expired or was released after the switch into PARTNER-DOWN state, for example ๐ŸŒธ.


4.3. Lazy Updates ๐Ÿฆฅ

[RFC7031] includes the requirement that failover must not introduce significant performance impact on server response times (see Sections 7 and 5.2.2 of [RFC7031]) ๐Ÿ’–. To meet that, a server running the failover protocol has to be able to respond to a DHCP client without waiting to update its failover partner whenever the binding database changes ๐Ÿš€. The "lazy update" mechanism lets a server allocate a new lease or extend an existing one, respond to the DHCP client, and then update its failover partner when it has time ๐Ÿซถ.

The lazy update mechanism doesn't add any delay to server responses, but it does bring other headaches ๐Ÿ˜ญ. The big problem is this: if a server fails after it tells a DHCP client about a particular valid lifetime but before it updates its failover partner, the partner will eventually think the client's lease has expired ๐Ÿ’€. Meanwhile, the DHCP client still has a valid lease on that address or prefix ๐Ÿ™ˆ. It's also possible that the failover partner has no record at all of the lease that went to the DHCP client ๐Ÿ‘€. Both of these problems are handled by using the MCLT when allocating or extending leases (see Section 4.4) โœจ.

4.4. Maximum Client Lead Time (MCLT) โœจ

Okay so, lazy updates can get a little messy ๐Ÿ™ˆ (see Section 4.3), which is why there's a time interval called the "Maximum Client Lead Time" (MCLT). It's defined, and it has to be known by both the primary server and the secondary server ๐Ÿซถ. Using it properly puts an upper bound on how far apart two lifetimes can drift: the valid lifetime a server hands to a DHCP client, and the valid lifetime that server's failover partner knows about.

The MCLT is usually way smaller than the valid lifetime a server is set up to offer a client, so there has to be a trick that lets the server still give out the configured valid lifetime ๐ŸŽ€. During a lazy update, the updating server tells its failover partner a partner lifetime that's longer than the valid lifetime it gave the DHCP client before, and also longer than the valid lifetime the server is configured to give a client. That way, the next time the client renews, the server can hand over the configured valid lifetime. The time it gives out won't go more than the MCLT past the partner lifetime its partner acknowledged, or the current time. It's giving careful planning ๐Ÿ’…

The fundamental relationship the failover protocol depends on is this: the lease expiration time known to a DHCP client MUST NOT be greater by more than the MCLT beyond the later of the partner lifetime acknowledged by that server's failover partner or the current time ๐Ÿ”ฅ. That's the main rule, and the rest of this section makes it more explicit.

The failover protocol makes a DHCP server deal with several different lease intervals, and it puts specific restrictions on how they relate ๐Ÿงš. The point of those restrictions is to let the partner make certain assumptions when the servers can't talk to each other.

In the following explanation, all of the lifetimes are "valid" lifetimes, in the context of [RFC3315] ๐Ÿ’œ. Here are the different times:

  • desired lifetime: The lease interval a DHCP server would like to give a DHCP client if the failover protocol didn't put any restrictions on it. Figuring this out is outside the scope of the failover protocol. Usually it's the result of external configuration of the DHCP server.
  • actual lifetime: The lease interval a DHCP server actually hands out to a DHCP client. It can be shorter than the desired lifetime (as explained below).
  • partner lifetime: The lease expiration interval the local server sends to its partner in a BNDUPD message.
  • acknowledged partner lifetime: The partner lifetime the partner server has most recently acknowledged in a BNDREPLY message.

4.4.1. MCLT Example โœจ

Let's walk through an example to see the MCLT in action ๐Ÿฆ‹. The values are arbitrarily chosen, so please don't treat them as recommended values. In this case, the MCLT is 1 hour. The desired lifetime is 3 days, and its renewal time is half the lifetime.

When a server makes an offer for a new lease on an IPv6 address to a DHCP client, it works out the desired lifetime (here, 3 days). Then it checks the acknowledged partner lifetime (which, in this case, is zero) and figures out the remaining time left to run, which is also zero. It adds the MCLT to that value. The actual lifetime can't be allowed to go past the remainder of the current acknowledged partner lifetime plus the MCLT, so the offer to the client is for the remainder of the current acknowledged partner lifetime (zero) plus the MCLT. So the actual lifetime is 1 hour (the MCLT) โฐ.

Once the server has sent the REPLY to the DHCP client, it updates its failover partner with the lease information using a BNDUPD message. The partner lifetime is made up of the T1 fraction (1/2) of the actual lifetime, added to the desired lifetime. So the failover partner gets a BNDUPD message with a partner lifetime of 1/2 hour + 3 days ๐Ÿ“.

When the primary server gets a BNDREPLY to its update of the secondary server's (partner's) partner lifetime, it records that as the acknowledged partner lifetime. A server MUST NOT send a BNDREPLY message in response to a BNDUPD message until it's sure the information in the BNDUPD message has been updated in its lease database. See Section 7.5.2. So when the primary server gets a BNDREPLY from the secondary server, it can be sure the secondary has recorded the partner lifetime in its stable storage ๐Ÿ”’.

When the DHCP client tries to renew at T1 (about 1/2 hour after the start of the lease), the primary server works out the desired lifetime again, which is still 3 days. Then it compares that with the original acknowledged partner lifetime (1/2 hour + 3 days) and adjusts for the time that has passed since the secondary was last updated (1/2 hour). The remaining time for the acknowledged partner interval is 3 days. Adding the MCLT gives 3 days plus 1 hour, which is more than the desired lifetime of 3 days. So the client can have its lease renewed for the desired lifetime, which is 3 days ๐ŸŽ‰.

After the client's renewal REPLY is done, the primary DHCP server updates the secondary DHCP server and works out the partner lifetime as the T1 fraction of the actual client lifetime (1/2 of 3 days = 1.5 days). It adds the desired lifetime of 3 days to that, for a total partner lifetime of 4.5 days. This way, the primary tries to keep the secondary "leading" the client in its understanding of the client's lifetime, so it can always offer the client the desired lifetime ๐Ÿ‘‘.

Once the initial actual client lifetime of the MCLT has passed, the failover protocol acts pretty much like DHCP does today when it comes to lifetimes. But the guarantee that the actual client lifetime will never go past the partner server's remaining acknowledged partner lifetime by more than the MCLT is what allows full recovery from a bunch of different DHCP server failures ๐ŸŒˆ.

 Fundamental relationship:
   lease time = floor( desired lifetime, acked-partner-lifetime + MCLT )

  Initial conditions: MCLT = 1h, desired lifetime = 3d

             DHCPv6               Primary             Secondary
      time   Client               Server               Server

               | >-SOLICIT------>    |                    |
               |  acknowledged partner lifetime = 0       |
               |  lease time = floor( 3d, 0 + 1h ) = 1h   |
               |   <-----ADVERTISE-< |                    |
               |    lease-time = 1h  |                    |
               | >-REQUEST------>    |                    |
        t      |   <---------REPLY-< |                    |
               |    lease-time = 1h  |                    |
               |                     |  >-BNDUPD------>   |
               |                     |  partner-lifetime = 1/2h + 3d
               |                     |    <----BNDREPLY-< |
               |                     |  partner-lifetime = 1/2h + 3d
               |acknowledged partner lifetime = 1/2h + 3d |
  1/2h passes ...                   ...                  ...
     t+1/2h    | >-RENEW-------->    |                    |
               |   acknowledged partner lifetime = 3d     |
               |   lease time = floor( 3d, 3d + 1h ) = 3d |
               |   <---------REPLY-< |                    |
               |   lease-time = 3d   |                    |
               |                     | >-BNDUPD------->   |
               |                     |  partner-lifetime = 1.5d + 3d
               |                     |    <----BNDREPLY-< |
               |                     |  partner-lifetime = 1.5d + 3d
               |acknowledged partner lifetime = 1.5d + 3d |
  1.5d passes ...                   ...                  ...
               |                     |                    |
 t+1.5d + 1/2h | >-RENEW-------->    |                    |
               |  acknowledged partner lifetime = 3d      |
               |   lease time = floor( 3d, 3d + 1h ) = 3d |
               |   <---------REPLY-< |                    |
               |   lease-time = 3d   |                    |
               |                     | >-BNDUPD------->   |
               |                     |  partner-lifetime = 1.5d + 3d
               |                     |    <----BNDREPLY-< |
               |                     |  partner-lifetime = 1.5d + 3d
               |acknowledged partner lifetime = 1.5d + 3d |

                          Figure 1: MCLT Example

5. Message and Option Definitions ๐ŸŽ€

5.1. Message Framing for TCP ๐Ÿ’Œ

Failover communication happens over a TCP connection set up between the partners ๐Ÿค. The failover protocol uses the framing format specified in Section 5.1 of "DHCPv6 Bulk Leasequery" [RFC5460], but it uses different message types with a different message format, as described in Section 5.2 of this document. The TCP connection between failover servers is made to a specific port, the dhcp-failover port, which is port 647 ๐Ÿฆ‹. All information is sent over the connection as typical DHCP messages that carry DHCP options, following the format defined in Section 22.1 of [RFC3315] โœจ.

5.2. Failover Message Format ๐Ÿ’–

okay bestie, every failover message follows the same basic layout: a fixed-size header, then a variable options area for extra stuff ๐ŸŽ€. Everything in the header and in any options is in network byte order ๐Ÿงš, so no mixing it up.

This diagram shows the format, which is compatible with the format in Section 6 of [RFC3315]. It's the shape of the DHCP messages that failover partners swap ๐Ÿฆ‹

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    msg-type   |               transaction-id                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           sent-time                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               .
.                            options                            .
.                           (variable)                          .
.                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Here's what each field does:

  • msg-type tells you which DHCP message type this is. The available types are listed below ๐Ÿ“‹
  • transaction-id is the transaction-id for this message exchange ๐Ÿ”
  • sent-time is when the message was transmitted, set as close to transmission as practical. It's counted in seconds since midnight (UTC), January 1, 2000, modulo 2^32. It's used to figure out the time skew between failover partners โฐ
  • options are the options carried in this message. All of them are defined in the "Option Codes" sub-registry of the "Dynamic Host Configuration Protocol for IPv6 (DHCPv6)" registry. A bunch of existing DHCPv6 options get reused, and a few more are defined in this document โœจ

5.3. Messages ๐Ÿ“ฌ

okay so, here are the brand-new message types made for failover chats ๐Ÿ’Œ

5.3.1. BNDUPD

BNDUPD (24) is the binding update message ๐Ÿ’…. It's how a server sends its binding lease changes over to its partner. At most one OPTION_CLIENT_DATA option may appear in a BNDUPD message. Not all the data in a BNDUPD gets packed into OPTION_CLIENT_DATA, though. Info about delegable prefixes that aren't currently handed out to a particular client rides along in BNDUPD messages, just not inside OPTION_CLIENT_DATA. The partner is expected to reply with a BNDREPLY message.

5.3.2. BNDREPLY

BNDREPLY (25) is the binding acknowledgement message ๐Ÿซถ. It confirms that a BNDUPD got received. It can be a positive or a negative response, like if there's a detected lease conflict ๐Ÿ’€

5.3.3. POOLREQ

POOLREQ (26) is the pool request message ๐Ÿ“. The secondary server uses it to ask the primary server for some allocation of delegable prefixes. The primary replies with a POOLRESP message.

5.3.4. POOLRESP

POOLRESP (27) is the pool response message ๐Ÿงš. The primary server uses it to say "got it, I received your POOLREQ." It also ensures delegable prefixes stay balanced between the primary and secondary servers โš–๏ธ. Important detail: it does NOT mean every BNDUPD that might come out of a rebalance has been sent or answered yet. It only means the primary accepted the job of checking the balance and fixing it if needed ๐ŸŒธ

5.3.5. UPDREQ

UPDREQ (28) is the update request message ๐Ÿ™. One server uses it to ask its partner to send every binding database change that hasn't been confirmed yet. The partner is expected to respond with zero or more BNDUPD messages, followed by an UPDDONE message. That UPDDONE signals that all the BNDUPD messages have been sent and that a matching BNDREPLY has been received for each one ๐ŸŽฏ

5.3.6. UPDREQALL

UPDREQALL (29) is the update request all message ๐ŸŒˆ. It's the big one: one server asks the other to send all of its binding database information, so the requester can recover from a total loss of its own binding database ๐Ÿ˜ญ. A server that gets this request replies with zero or more BNDUPD messages, followed by an UPDDONE message. That UPDDONE signals that all the BNDUPD messages have been sent and that a matching BNDREPLY has been received for each one ๐Ÿ‘‘

5.3.7. UPDDONE

UPDDONE (30) is the update done message โœ…. The server answering an UPDREQ or UPDREQALL uses it to say that every requested update has been sent and acked by the requesting server.

5.3.8. CONNECT

CONNECT (31) is the connect message ๐Ÿ”Œ. The primary server uses it to set up a failover connection with the secondary server, and to send over several important configuration attributes between the two servers ๐ŸŽ€. The partner is expected to confirm by replying with a CONNECTREPLY message.

5.3.9. CONNECTREPLY

CONNECTREPLY (32) is the connect acknowledgement message ๐Ÿฅฐ. The secondary server uses it to answer a CONNECT message from the primary server.

5.3.10. DISCONNECT

DISCONNECT (33) is the disconnect message ๐Ÿ‘‹. Either server can send it when it's closing a connection and shutting down. No response is required for this one. The DISCONNECT message SHOULD contain an OPTION_STATUS_CODE option with an appropriate status. Often, that status will be ServerShuttingDown. See Section 5.6. A server SHOULD include a descriptive message explaining what caused the disconnect ๐Ÿ“

5.3.11. STATE

STATE (34) is the state message ๐Ÿ”„. Either server uses it to tell its partner about a change in failover state. Sometimes it also gets used to tell the partner the current state, for example right after a connection is established while in the COMMUNICATIONS-INTERRUPTED or PARTNER-DOWN states ๐Ÿฆ‹

5.3.12. CONTACT

CONTACT (35) is the contact message ๐Ÿ’œ. Either server sends it so the partner keeps seeing the connection as working. It MUST be transmitted periodically over every established connection if other message traffic is not flowing, and it MAY be sent at any time. See Section 6.5. This is the heartbeat energy we need ๐Ÿ’“


5.4. Transaction-id ๐Ÿ”ข

okay, the initiator of a message exchange MUST set the transaction-id (see Section 5.2). So all the messages above, except BNDREPLY, POOLRESP, UPDDONE, and CONNECTREPLY, have to set the transaction-id โœจ. The transaction-id MUST be unique among all currently outstanding messages sent to the failover partner ๐Ÿ”’. The easy way to make sure of that is to just use an incrementing value, with one caveat ๐Ÿ‘€.

The caveat is that UPDREQ and UPDREQALL messages can sit around for a long time before the UPDDONE shows up. Usually the partner does most of the message starting, but it's remotely possible that the server which started the UPDREQ or UPDREQALL also sends enough messages to wrap the 24-bit transaction-id. If that happens, it could end up duplicating the transaction-id of the outstanding UPDREQ or UPDREQALL. So it's important that the transaction-id of a currently outstanding UPDREQ or UPDREQALL is not reused in any message started before the matching UPDDONE comes back ๐Ÿซฃ


5.5. Options ๐ŸŽ€

These are the new options that get defined.

5.5.1. OPTION_F_BINDING_STATUS

The binding-status is an implementation-independent way of representing the status (or the state) of a lease on an IPv6 address or prefix ๐ŸŒธ. It's an unsigned byte, and this option's code is 114.

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    OPTION_F_BINDING_STATUS    |           option-len          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| binding-status|
+-+-+-+-+-+-+-+-+
  • option-code is OPTION_F_BINDING_STATUS (114)
  • option-len is 1
  • binding-status is the binding-status value. Check the table below ๐Ÿ‘‡
  Value   binding-status
  -----   --------------
  0       reserved
  1       ACTIVE
  2       EXPIRED
  3       RELEASED
  4       PENDING-FREE
  5       FREE
  6       FREE-BACKUP
  7       ABANDONED
  8       RESET

The binding-status values are discussed in Section 7.2 ๐Ÿง .

5.5.2. OPTION_F_CONNECT_FLAGS

This option gives you flags that show attributes of the server that's connecting ๐Ÿš€. It's an unsigned 16-bit integer in network byte order, and its code is 115.

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    OPTION_F_CONNECT_FLAGS     |           option-len          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             flags             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • option-code is OPTION_F_CONNECT_FLAGS (115)
  • option-len is 2
  • flags holds the flag bits, laid out like this ๐Ÿ‘‡
   0                   1
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |           MBZ               |F|
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The bits are numbered from the most significant bit in network byte order, and they work like this:

  • Bits 0-14 (MBZ): Must be zero.
  • Bit 15 (F), FIXED_PD_LENGTH: Set this to 1 to say that all prefixes delegated from a given delegable prefix have the same prefix length (size). If it's not set, the prefixes delegated from one delegable prefix may have different sizes ๐Ÿ“

If the FIXED_PD_LENGTH bit is not set, it means prefixes of a range of sizes can be delegated from a given delegable prefix ๐ŸŒˆ. Heads up though: if FIXED_PD_LENGTH is set, each delegable prefix can still have its own fixed size. This flag doesn't mean every delegated prefix is the same size. It means all prefixes delegated from the same delegable prefix are the same size โœจ

If the FIXED_PD_LENGTH bit is set, the length used for each prefix is specified separately from the failover protocol. Both failover partners still have to know it, though. It might be set in the configuration for each delegable prefix, or it might be fixed for the entire server ๐Ÿ”ฅ

5.5.3. OPTION_F_DNS_REMOVAL_INFO ๐Ÿงน

Okay so this option is basically the info pack you need to clean up a DNS name that the failover partner put in ๐Ÿงน๐Ÿ’… Its code is 116, obviously.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_DNS_REMOVAL_INFO   |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      encapsulated-options                     |
    |                           (variable)                          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code       OPTION_F_DNS_REMOVAL_INFO (116)
    option-len        variable
    options           Three possible encapsulated options:
                         OPTION_F_DNS_HOST_NAME
                         OPTION_F_DNS_ZONE_NAME
                         OPTION_F_DNS_FLAGS

5.5.3.1. OPTION_F_DNS_HOST_NAME ๐ŸŒ

This one carries the hostname that the failover partner entered into DNS ๐Ÿ’–

The name is encoded the DNS way from [RFC1035], which is also the format Section 8 of [RFC3315] uses ๐Ÿงš

The code for this option is 117 โœจ

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |     OPTION_F_DNS_HOST_NAME    |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               .
    .                                                               .
    .                           host-name                           .
    .                           (variable)                          .
    .                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code       OPTION_F_DNS_HOST_NAME (117)
    option-len        length of host-name
    host-name         hostname encoded per RFC 1035

5.5.3.2. OPTION_F_DNS_ZONE_NAME ๐Ÿ—บ๏ธ

This one carries the zone name that the failover partner entered into DNS ๐ŸŽ€

Same deal as the hostname: it's a DNS name encoded using the format from [RFC1035], as also specified in Section 8 of [RFC3315] ๐Ÿซถ

The code for this option is 118 ๐Ÿฆ‹

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |     OPTION_F_DNS_ZONE_NAME    |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               .
    .                                                               .
    .                           zone-name                           .
    .                           (variable)                          .
    .                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    option-code       OPTION_F_DNS_ZONE_NAME (118)
    option-len        length of zone-name
    zone-name         zone name encoded per RFC 1035

5.5.3.3. OPTION_F_DNS_FLAGS ๐Ÿšฉ

This option is the flag squad ๐Ÿšฉโœจ It tells you what needs to happen to remove this DNS name.

It's an unsigned 16-bit integer in network byte order ๐Ÿ”ข

The code for this option is 119 ๐Ÿ’œ

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       OPTION_F_DNS_FLAGS      |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |             flags             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code       OPTION_F_DNS_FLAGS (119)
    option-len        2
    flags             flag bits.  See below:

Here's the bit layout, numbered from the most significant bit in network byte order ๐Ÿง 

       0                   1
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           MBZ         |U|S|R|F|
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

And here's what each bit does:

0-11:   MBZ
        Must be zero.
12 (U): USING_REQUESTED_FQDN
        Set to 1 to indicate that the name used came from the
        Fully Qualified Domain Name (FQDN) that was received
        from the client.
13 (S): SYNTHESIZED_NAME
        Set to 1 to indicate that the name was synthesized
        based on some algorithm.
14 (R): REV_UPTODATE
        Set to 1 to indicate that the reverse zone is up to date.
15 (F): FWD_UPTODATE
        Set to 1 to indicate that the forward zone is up to date.
If both the U bit and the S bit are unset, then the name must have been provided from some alternative configuration, such as client registration in some database accessible to the DHCP server. ๐Ÿ™ˆ

5.5.4. OPTION_F_EXPIRATION_TIME โฐ

This option holds the greatest lifetime this server has ever acked to its partner in a BNDREPLY message for a particular lease or prefix ๐ŸŽ€ This MUST be an absolute time (i.e., seconds since midnight January 1, 2000 UTC, modulo 2^32).

It's an unsigned 32-bit integer in network byte order ๐Ÿ”ข

The code for this option is 120 โœจ

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_EXPIRATION_TIME    |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        expiration-time                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code         OPTION_F_EXPIRATION_TIME (120)
    option-len          4
    expiration-time     The expiration time.  This MUST be an
                        absolute time (i.e., seconds since midnight
                        January 1, 2000 UTC, modulo 2^32).

5.5.5. OPTION_F_MAX_UNACKED_BNDUPD ๐Ÿ“ฌ

This option says how many BNDUPD messages this server is ready to accept over the TCP connection without the TCP connection getting blocked ๐Ÿšฆ

It's an unsigned 32-bit integer in network byte order ๐Ÿ”ข

The code for this option is 121 ๐Ÿ’…

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  OPTION_F_MAX_UNACKED_BNDUPD  |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                       max-unacked-bndupd                      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code           OPTION_F_MAX_UNACKED_BNDUPD (121)
    option-len            4
    max-unacked-bndupd    Maximum number of unacked BNDUPD messages
                          allowed

5.5.6. OPTION_F_MCLT ๐Ÿฆ‹

The Maximum Client Lead Time (MCLT) is the upper bound on how far apart the valid lifetime a server hands a DHCP client can be from the valid lifetime that server's failover partner knows about ๐Ÿ‘€ It's an interval, measured in seconds. See Section 4.4 ๐Ÿ“–

It's an unsigned 32-bit integer in network byte order ๐Ÿ”ข

The code for this option is 122 ๐ŸŒธ

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |         OPTION_F_MCLT         |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                              mclt                             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code       OPTION_F_MCLT (122)
    option-len        4
    mclt              The MCLT, in seconds

5.5.7. OPTION_F_PARTNER_LIFETIME ๐Ÿงš

This option tells the partner when it can consider an IPv6 address expired and reuse it ๐Ÿซถ This MUST be an absolute time (i.e., seconds since midnight January 1, 2000 UTC, modulo 2^32).

It's an unsigned 32-bit integer in network byte order ๐Ÿ”ข

The code for this option is 123 ๐Ÿ’–

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_PARTNER_LIFETIME   |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        partner-lifetime                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code          OPTION_F_PARTNER_LIFETIME (123)
    option-len           4
    partner-lifetime     The partner lifetime.  This MUST be an
                         absolute time (i.e., seconds since midnight
                         January 1, 2000 UTC, modulo 2^32).

5.5.8. OPTION_F_PARTNER_LIFETIME_SENT ๐Ÿ”

This option is basically an echo ๐Ÿ” It carries the time that came in an OPTION_F_PARTNER_LIFETIME option (Section 5.5.7). It's an exact duplicate of that received time, and it is not adjusted in any way ๐Ÿ™Œ This MUST be an absolute time (i.e., seconds since midnight January 1, 2000 UTC, modulo 2^32).

It's an unsigned 32-bit integer in network byte order ๐Ÿ”ข

The code for this option is 124 ๐ŸŒˆ

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |OPTION_F_PARTNER_LIFETIME_SENT |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      partner-lifetime-sent                    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    option-code              OPTION_F_PARTNER_LIFETIME_SENT (124)
    option-len               4
    partner-lifetime-sent    The partner-lifetime received in an
                             OPTION_F_PARTNER_LIFETIME option.
                             This MUST be an absolute time
                             (i.e., seconds since midnight
                             January 1, 2000 UTC, modulo 2^32).

5.5.9. OPTION_F_PARTNER_DOWN_TIME ๐Ÿ’”

okay bestie, this one is the "when did we last lose each other" option ๐Ÿ˜ญ. It tells you the exact moment the server most recently lost communications with its failover partner. This MUST be an absolute time, so we're talking seconds since midnight January 1, 2000 UTC, modulo 2^32 ๐Ÿ•› no vibes-based timestamps allowed ๐Ÿ’….

This is an unsigned 32-bit integer in network byte order ๐Ÿ”ข. The code for this option is 125 ๐ŸŽ€.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_PARTNER_DOWN_TIME  |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                       partner-down-time                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
option-code          OPTION_F_PARTNER_DOWN_TIME (125)
option-len           4
partner-down-time    Contains the PARTNER-DOWN time.  This MUST be
                     an absolute time (i.e., seconds since midnight
                     January 1, 2000 UTC, modulo 2^32).

5.5.10. OPTION_F_PARTNER_RAW_CLT_TIME ๐Ÿฆ‹

this one is giving "the last time my partner touched this client" ๐Ÿ‘€. It's the moment the partner most recently interacted with the DHCP client linked to this IPv6 address or prefix. This MUST be an absolute time (seconds since midnight January 1, 2000 UTC, modulo 2^32) โฐ.

This is an unsigned 32-bit integer in network byte order ๐Ÿ”ข. The code for this option is 126 โœจ.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | OPTION_F_PARTNER_RAW_CLT_TIME |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      partner-raw-clt-time                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
option-code             OPTION_F_PARTNER_RAW_CLT_TIME (126)
option-len              4
partner-raw-clt-time    Contains the partner-raw-clt-time.
                        This MUST be an absolute time
                        (i.e., seconds since midnight
                        January 1, 2000 UTC, modulo 2^32).

5.5.11. OPTION_F_PROTOCOL_VERSION ๐ŸŒˆ

the protocol version lets one failover partner figure out which version of the protocol the other one is using, so changes and upgrades can happen later on ๐Ÿš€. There are two components so that big and small changes can both live in one 32-bit number ๐Ÿ’œ. The idea is that big changes bump up major-version, and small changes bump up minor-version. Later updates and extensions of this document can define these changes in any way they like, so this document doesn't try to pin down what "large" and "small" mean ๐Ÿคทโ€โ™€๏ธ.

This option consists of two unsigned 16-bit integers in network byte order ๐Ÿ”ข. The code for this option is 127 ๐ŸŽ€.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_PROTOCOL_VERSION   |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |        major-version          |        minor-version          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
option-code       OPTION_F_PROTOCOL_VERSION (127)
option-len        4
major-version     The major version of the protocol.  Initially 1.
minor-version     The minor version of the protocol.  Initially 0.

5.5.12. OPTION_F_KEEPALIVE_TIME ๐Ÿซฃ

this option is the number of seconds (an interval) the server has to hear a message from its partner within. If nothing shows up in that window, the server will assume communications from the partner are not "OK" ๐Ÿ˜ฌ. This is an unsigned 32-bit integer in network byte order ๐Ÿ”ข, and the code for it is 128 ๐Ÿ’–.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    OPTION_F_KEEPALIVE_TIME    |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         keepalive-time                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
option-code       OPTION_F_KEEPALIVE_TIME (128)
option-len        4
receive-time      The keepalive-time.  An interval of seconds.

5.5.13. OPTION_F_RECONFIGURE_DATA ๐Ÿ”‘

this option carries everything one failover partner needs to use the reconfigure-key that was created on the other failover partner ๐Ÿ—๏ธ. The code for this option is 129 ๐ŸŽ€.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_RECONFIGURE_DATA   |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        reconfigure-time                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               .
    .                                                               .
    .                        reconfigure-key                        .
    .                           (variable)                          .
    .                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
option-code         OPTION_F_RECONFIGURE_DATA (129)
option-len          4 + length of reconfigure-key
reconfigure-time    Time at which reconfigure-key was created.
                    This MUST be an absolute time
                    (i.e., seconds since midnight
                    January 1, 2000 UTC, modulo 2^32).
reconfigure-key     The reconfigure key

5.5.14. OPTION_F_RELATIONSHIP_NAME ๐Ÿท๏ธ

this option gives the failover relationship a name ๐Ÿ’…. It's super handy when two failover servers have multiple failover relationships between them ๐Ÿ‘ฏ. It's a UTF-8 encoded text string that's suitable for display to an end user. It MUST NOT be null-terminated ๐Ÿšซ.

The code for this option is 130 โœจ.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   OPTION_F_RELATIONSHIP_NAME  |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               .
    .                                                               .
    .                       relationship-name                       .
    .                           (variable)                          .
    .                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
option-code          OPTION_F_RELATIONSHIP_NAME (130)
option-len           length of relationship-name
relationship-name    A UTF-8 encoded text string suitable for
                     display to an end user.  MUST NOT be
                     null-terminated.

5.5.15. OPTION_F_SERVER_FLAGS ๐ŸŽ€

the OPTION_F_SERVER_FLAGS option tells you about the failover endpoint that's sending it ๐Ÿ“ก. It's an unsigned byte, and the code for it is 131 ๐ŸŒธ.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |     OPTION_F_SERVER_FLAGS     |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  server-flags |
    +-+-+-+-+-+-+-+-+
option-code       OPTION_F_SERVER_FLAGS (131)
option-len        1
server-flags      The server flags.  See below:
 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|   MBZ   |A|S|C|
+-+-+-+-+-+-+-+-+

The bits (numbered from the most significant bit in network byte order) are used as follows ๐Ÿ”Ž:

0-4:   MBZ
       Must be zero.
5 (A): ACK_STARTUP
       Set to 1 to indicate that the OPTION_F_SERVER_FLAGS option
       that was most recently received contained the
       STARTUP bit set.
6 (S): STARTUP
       MUST be set to 1 whenever the server is in STARTUP state.
7 (C): COMMUNICATED
       Set to 1 to indicate that the sending server has
       communicated with its partner.

5.5.16. OPTION_F_SERVER_STATE ๐ŸŒŸ

the OPTION_F_SERVER_STATE option tells you the endpoint state of the server that sent it ๐Ÿงš. It's an unsigned byte, and the code for it is 132 ๐Ÿ‘‘.

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |     OPTION_F_SERVER_STATE     |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  server-state |
    +-+-+-+-+-+-+-+-+
option-code       OPTION_F_SERVER_STATE (132)
option-len        1
server-state      Failover endpoint state
   Value   Server State
   -----   -------------------------------------------------------------
   0       reserved
   1       STARTUP                      Startup state (1)
   2       NORMAL                       Normal state
   3       COMMUNICATIONS-INTERRUPTED   Communications interrupted
   4       PARTNER-DOWN                 Partner down
   5       POTENTIAL-CONFLICT           Synchronizing
   6       RECOVER                      Recovering bindings from partner
   7       RECOVER-WAIT                 Waiting out MCLT after RECOVER
   8       RECOVER-DONE                 Interlock state prior to NORMAL
   9       RESOLUTION-INTERRUPTED       Comm. failed during resolution
   10      CONFLICT-DONE                Primary resolved its conflicts

These states are discussed in detail in Section 8 ๐Ÿ“š.

(1) The STARTUP state is never sent to the partner server; it is
    indicated by the STARTUP bit in the OPTION_F_SERVER_FLAGS option
    (see Section 8.3).

5.5.17. OPTION_F_START_TIME_OF_STATE โœจ

okay bestie, this option tells you when the state started holding its current value ๐Ÿ•ฐ๏ธ When it shows up in a STATE message, the state it's talking about is the server endpoint state ๐Ÿ’… When it lives inside an IA_NA-options, IA_TA-options, or IA_PD-options field, it's about the binding-status value in the OPTION_IA_NA, OPTION_IA_TA, or OPTION_IA_PD option, respectively ๐ŸŽ€ This MUST be an absolute time (i.e., seconds since midnight January 1, 2000 UTC, modulo 2^32) ๐Ÿซถ

It's an unsigned 32-bit integer in network byte order ๐Ÿงš

The code for this option is 133 ๐Ÿฆ‹

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  OPTION_F_START_TIME_OF_STATE |           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      start-time-of-state                      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code            OPTION_F_START_TIME_OF_STATE (133)
    option-len             4
    start-time-of-state    The start time of the current state.
                           This MUST be an absolute time (i.e., seconds
                           since midnight January 1, 2000 UTC,
                           modulo 2^32).

5.5.18. OPTION_F_STATE_EXPIRATION_TIME ๐ŸŒธ

okay so this option says when the current state of this lease is going to expire โณ It MUST be an absolute time (i.e., seconds since midnight January 1, 2000 UTC, modulo 2^32) ๐Ÿ’–

Heads up ๐Ÿ‘€: states other than ACTIVE can have a time attached too! EXPIRED might have one if there's some kind of "grace period" where the lease sits around for a bit after expiring and doesn't get handed out again right away. ABANDONED might have one if the failover servers have a time after which an ABANDONED lease can be put back into a pool for a client to get allocated ๐Ÿซง Basically, if there's an OPTION_STATE_EXPIRATION_TIME attached to a particular state, that means the state is going to expire and move to a different state at that time โœจ

It's an unsigned 32-bit integer in network byte order ๐Ÿงš

The code for this option is 134 ๐Ÿฆ‹

     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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | OPTION_F_STATE_EXPIRATION_TIME|           option-len          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                     state-expiration-time                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    option-code              OPTION_F_STATE_EXPIRATION_TIME (134)
    option-len               4
    state-expiration-time    The time at which the current state of the
                             lease will expire.  This MUST be an
                             absolute time (i.e., seconds since midnight
                             January 1, 2000 UTC, modulo 2^32).

5.6. Status Codes ๐Ÿ’…

okay so these are the new status codes you can use in the OPTION_STATUS_CODE option ๐ŸŽ€ Here's the whole lineup:

  • AddressInUse (16): one client on one server has leases that clash with the leases that same client has on another server ๐Ÿ˜ฌ Or, the address could be tied to a different Identity Association Identifier (IAID) on each server.
  • ConfigurationConflict (17): the configuration implied by the info in a BNDUPD message (like the IPv6 address or prefix address) directly clashes with what the receiving server already knows ๐Ÿ’ฅ
  • MissingBindingInformation (18): there isn't enough info in a BNDUPD message to actually process it ๐Ÿ™ˆ
  • OutdatedBindingInformation (19): the server's binding database disagrees with an incoming BNDUPD message, and the server thinks its own database is the one that matches reality ๐Ÿง
  • ServerShuttingDown (20): the server is going down on purpose, either because an operator said so or because of some other planned shutdown ๐ŸŒ™
  • DNSUpdateNotSupported (21): a server gets a BNDUPD message with DNS update info in it, but it doesn't support DNS update ๐Ÿ™…โ€โ™€๏ธ
  • ExcessiveTimeSkew (22): a server notices the gap between its current time and its partner's current time is bigger than 5 seconds โฐ

6. Connection Management ๐Ÿฆ‹

okay, so failover partners talk to each other over a long-lived TCP connection ๐Ÿงต The primary server is always the one that starts this connection, and if the connection gets lost, it's the primary's job to try reconnecting to the secondary server ๐Ÿ” The detailed process the primary follows when starting a connection, and the one the secondary follows when answering, is the one from Section 6.1. It runs every single time a connection gets set up, no matter whether the partners have connected before ๐Ÿ’–

6.1. Creating Connections ๐ŸŒˆ

Every primary server implementing the failover protocol MUST keep trying, periodically, to create a TCP connection to the dhcp-failover port (647) of all of its configured partners ๐Ÿ”„ How often it tries is up to the implementation, and that interval SHOULD be configurable โฑ๏ธ If a connection gets turned down with a CONNECTREPLY message that has an OPTION_STATUS_CODE option in it, or with a DISCONNECT message, the server SHOULD try to connect to that server less often ๐Ÿข But it MUST still keep trying periodically, no giving up ๐Ÿซถ

Every secondary server implementing the failover protocol MUST listen for TCP connection attempts on the dhcp-failover port (647) from a primary server ๐Ÿ‘‚

After a primary server successfully establishes a TCP connection to a secondary server, it MUST carry on with the connection process described in Section 8.2 of [RFC7653] ๐Ÿค In that section's language, the primary failover server acts as the "requestor" and the secondary failover server acts as the "DHCP server" ๐ŸŽญ The first message sent over that new connection is a CONNECT message, not an ACTIVELEASEQUERY message ๐Ÿ’Œ

When a secondary server gets a connection attempt, the only thing it knows is the IP address of the partner that's trying to connect ๐Ÿ•ต๏ธโ€โ™€๏ธ If it has any relationships with the connecting server where it's the secondary, it should operate as described in Section 9.1 of [RFC7653], with one twist: instead of waiting for an Active Leasequery message, it waits for a CONNECT message ๐Ÿง Once it gets that CONNECT message, it uses the info inside to figure out which relationship this connection is meant to serve ๐Ÿ”

If it has no secondary relationships with the connecting server, it MUST drop the connection ๐Ÿšซ

So, to sum it all up: a primary server MUST use a connection it started itself to send a CONNECT message ๐Ÿ“ค Every server that's a secondary in a relationship MUST listen for CONNECT messages from the primary server ๐Ÿ‘‚โœจ

When the CONNECT and CONNECTREPLY exchange successfully produces a working failover connection, the next message sent over a new connection is a STATE message. See Section 6.3 ๐Ÿงš Once the receiver gets that STATE message, it can consider communications "OK" ๐Ÿ’…

6.1.1. Sending a CONNECT Message ๐Ÿ’œ

The CONNECT message is sent with info about the failover configuration on the primary server ๐Ÿ“‹ It MUST contain at least the following information in the options area:

  • OPTION_F_PROTOCOL_VERSION containing the protocol version that the primary server will use when sending failover messages ๐Ÿ”ข
  • OPTION_F_MCLT containing the configured MCLT ๐ŸŽ€
  • OPTION_F_KEEPALIVE_TIME containing the number of seconds (an interval) within which the server must receive a message from its partner, or it will assume that communications from the partner are not "OK" โฒ๏ธ
  • OPTION_F_MAX_UNACKED_BNDUPD containing the maximum number of BNDUPD messages that this server is prepared to accept over the failover connection without causing the connection to block. This implements application-level flow control over the connection, so that a flood of BNDUPD messages does not cause the connection to block and thereby prevent other messages from being transmitted over the connection and received by the failover partner ๐ŸŒŠ๐Ÿšฆ
  • OPTION_F_RELATIONSHIP_NAME containing the name of the failover relationship this connection applies to. If there is no OPTION_F_RELATIONSHIP_NAME in the CONNECT message, it means there's only a single relationship between this pair of primary and secondary servers ๐Ÿ’ž
  • OPTION_F_CONNECT_FLAGS containing info about certain attributes of the connecting servers ๐Ÿท๏ธ

6.1.2. Receiving a CONNECT Message โœจ

okay so a server that gets a CONNECT message has to actually process what's in it and then decide whether to accept the connection ๐Ÿ’… here's the checklist it runs through:

  • sent-time: the secondary server checks the sent-time to see if it's within 5 seconds of its current time ๐Ÿ•ฐ๏ธ (see Section 7.1). if it's NOT, it returns ExcessiveTimeSkew in the OPTION_STATUS_CODE to reject the CONNECT message ๐Ÿ™…โ€โ™€๏ธ
  • OPTION_F_PROTOCOL_VERSION: the secondary server decides if the primary's protocol version is supported. if it isn't, it returns NotSupported in the OPTION_STATUS_CODE to reject the CONNECT message ๐Ÿ’€
  • OPTION_F_MCLT: use this MCLT supplied by the primary server ๐Ÿ’œ remember it and keep using it until some later CONNECT message supplies a different MCLT
  • OPTION_F_KEEPALIVE_TIME: remember the keepalive-time as the FO_KEEPALIVE_TIME (Section 6.5) when implementing the Unreachability Detection algorithm described in Section 6.6 ๐Ÿซถ
  • OPTION_F_MAX_UNACKED_BNDUPD: make sure the maximum number of unacked BNDUPD messages queued to the primary server never goes past the value in the OPTION_F_MAX_UNACKED_BNDUPD option ๐ŸŒธ
  • OPTION_F_CONNECT_FLAGS: make sure the secondary server can process the info from the primary as the flags describe ๐ŸŽ€ for example, if the secondary can't handle prefix delegation with variable-sized prefixes delegated from the same delegable prefix, and the primary says it can, the secondary SHOULD reject the connection. ngl this one's giving "read the fine print" energy ๐Ÿ™ˆ

Okay the next bit is a big deal ๐Ÿ”ฅ a CONNECT message SHOULD always get a CONNECTREPLY message back, either to (1) accept the connection, or (2) reject it by including an OPTION_STATUS_CODE option with a status-code that says why. if you're accepting, the CONNECTREPLY carries this stuff:

  • OPTION_F_PROTOCOL_VERSION, holding the protocol version the secondary server is using when it sends failover messages ๐Ÿฆ‹
  • OPTION_F_MCLT, holding the MCLT currently in use on the secondary server. this MUST equal the MCLT that was in the OPTION_F_MCLT option in the CONNECT message. no wiggle room bestie ๐Ÿ”’
  • OPTION_F_KEEPALIVE_TIME, holding the number of seconds (an interval) within which the server has to receive a message from its partner, or it'll assume the partner's communications aren't "OK" ๐Ÿ’œ
  • OPTION_F_MAX_UNACKED_BNDUPD, holding the max number of BNDUPD messages this server is ready to accept over the failover connection without the connection blocking. this is application-level flow control ๐ŸŒŠ so a flood of BNDUPD messages can't block the connection and stop other messages from getting sent and received by the failover partner. main character protection ๐Ÿ‘‘
  • OPTION_F_CONNECT_FLAGS, describing the attributes of the secondary server that the primary needs to know about โœจ

After sending a CONNECTREPLY that accepts the primary's CONNECT message, the secondary server MUST send a STATE message (see Section 6.3). periodt ๐Ÿ’–

6.1.3. Receiving a CONNECTREPLY Message โœจ

a server that gets a CONNECTREPLY message also has to process what's in it and decide whether to keep using the connection ๐Ÿงš here's how that goes:

  • OPTION_F_PROTOCOL_VERSION: the primary server decides if the secondary's protocol version is supported by the primary. if it's NOT, the primary sends a DISCONNECT message and drops the connection ๐Ÿšช if it IS supported, keep going. it's totally possible that the primary and secondary each end up sending the other a different version of the protocol ๐ŸŒˆ

the extent to which this works is going to be shaped partly by as-yet-unknown differences in the protocol versions themselves, and partly by what the two implementations in the failover relationship can actually do ๐Ÿค“

  • OPTION_F_MCLT: compare the MCLT received with the configured MCLT. if they're different, send a DISCONNECT message and drop the connection ๐Ÿ’…
  • OPTION_F_KEEPALIVE_TIME: remember the keepalive-time as the FO_KEEPALIVE_TIME (Section 6.5) when implementing the Unreachability Detection algorithm described in Section 6.6 ๐Ÿซถ
  • OPTION_F_MAX_UNACKED_BNDUPD: make sure the max number of unacked BNDUPD messages queued to the secondary server never goes past the value in the OPTION_F_MAX_UNACKED_BNDUPD option ๐ŸŒธ
  • OPTION_F_CONNECT_FLAGS: make sure the primary server can process the info from the secondary as the flags say. same example as before, flipped: if the primary can't handle prefix delegation with variable-sized prefixes delegated from the same delegable prefix, and the secondary says it can, the primary SHOULD drop the connection ๐Ÿ™ˆ

After receiving a CONNECTREPLY that accepted the primary's CONNECT message, the primary server MUST send a STATE message (see Section 6.3) โœจ


6.2. Endpoint Identification ๐Ÿงš

okay so a failover endpoint is always tied to a set of DHCP prefixes that are configured on the DHCP server where that endpoint lives ๐ŸŒธ a DHCP prefix MUST NOT be associated with more than one failover endpoint. one prefix, one endpoint, no sharing ๐Ÿ’…

the failover protocol SHOULD be set up with one failover relationship between each pair of failover servers. in that case there's one failover endpoint for that relationship on each failover partner ๐Ÿฆ‹ and this failover relationship MUST have a unique name ๐ŸŽ€

any failover endpoint can take actions and hold unique states ๐Ÿ‘‘

this doc talks about the failover protocol's behavior in terms of primary and secondary servers, instead of primary and secondary failover endpoints ๐Ÿ’œ but just remember that every "server" in here is really a failover endpoint living inside a particular process, and several failover endpoints can live in the same server process ๐ŸŒˆ

it's NOT the case that there's a unique failover endpoint for each prefix taking part in a failover relationship. on one server there's (typically) one failover endpoint per partner, no matter how many prefixes that partner and role are managing ๐Ÿ“ and on a particular server, any given prefix that takes part in failover is associated with exactly one failover endpoint โœจ

when a connection comes in from the partner, the unique failover endpoint the message is directed to gets determined ONLY by the IPv6 address of the partner, the relationship name, and the role of the receiving server ๐Ÿ”’


6.3. Sending a STATE Message ๐Ÿ’–

a server MUST send a STATE message to its failover partner whenever the state of the failover endpoint changes ๐Ÿ”ฅ sending the occasional duplicate STATE message won't cause any problems. but NOT updating the failover partner about a failover endpoint state change can, in lots of cases, leave the entire failover protocol inoperative ๐Ÿ’€

the STATE message carries info about the endpoint state of the failover relationship. it MUST contain at least the following info in the options area:

  • OPTION_F_SERVER_STATE, containing the state of this failover endpoint ๐ŸŒŠ
  • OPTION_F_SERVER_FLAGS, containing the flag values associated with this failover endpoint ๐ŸŽ€
  • OPTION_F_START_TIME_OF_STATE, containing the time when this became the state of this failover endpoint โฐ
  • OPTION_F_PARTNER_DOWN_TIME, containing the time that this failover endpoint went into PARTNER-DOWN state, if this server is in PARTNER-DOWN state. if this server ISN'T in PARTNER-DOWN state, don't include this option ๐Ÿ™…โ€โ™€๏ธ

the server sending a STATE message SHOULD make sure this info is written to stable storage before it gets enqueued to its failover partner ๐Ÿซถ


6.4. Receiving a STATE Message ๐ŸŒˆ

a server that gets a STATE message has to process the info in it and decide how to react. here's the run-down:

  • OPTION_F_SERVER_STATE: if this represents a change in state for the failover partner, react according to the instructions in Section 8.1. if the state is NOT PARTNER-DOWN, clear any memory of the partner-down-time ๐Ÿงน
  • OPTION_F_SERVER_FLAGS: remember these flags in an appropriate data area so they can be referenced later ๐Ÿ“ฆ
  • OPTION_F_START_TIME_OF_STATE: remember this info in an appropriate data area so it can be referenced later ๐Ÿ“ฆ
  • OPTION_F_PARTNER_DOWN_TIME: if the value of the OPTION_F_SERVER_STATE is PARTNER-DOWN, remember this info in an appropriate data area so it can be referenced later ๐Ÿ“ฆ

a server receiving a STATE message SHOULD make sure this info gets written to stable storage ๐Ÿ’œ


6.5. Connection Maintenance Parameters ๐Ÿ’…

these parameters and timers keep the connections between two failover servers healthy and honest ๐Ÿฉบ (the integrity of the connections, to be exact ๐Ÿค“)

Parameter                      Default  Description
---------------------------------------------------------------------
FO_KEEPALIVE_TIMER             timer    counts down to time
                                        connection assumed dead
                                        due to lack of messages

FO_KEEPALIVE_TIME              60       maximum time server will
                                        consider connection still up
                                        with no messages

FO_CONTACT_PER_KEEPALIVE_TIME  4        number of CONTACT messages
                                        to send during partner's
                                        FO_KEEPALIVE_TIME period

FO_SEND_TIMER                  timer    counts down to time to send
                                        next CONTACT message

FO_SEND_TIME                   15       maximum time to wait between
                                        sending CONTACT messages
                                        if no other traffic.
                                        Created from partner's
                                        FO_KEEPALIVE_TIME divided by
                                        FO_CONTACT_PER_KEEPALIVE_TIME

6.6. Unreachability Detection

okay so every partner MUST keep its own FO_SEND_TIMER for each failover connection ๐Ÿ’Œ every time a message goes out on that connection, the timer resets to FO_SEND_TIME and ticks down once per second. when it hits zero, a CONTACT message gets sent on that connection and the timer resets again โฐ the CONTACT message may be sent at any time, bestie. and an implementation MAY use extra mechanisms to detect that the partner is unreachable ๐Ÿ•ต๏ธโ€โ™€๏ธ

FO_SEND_TIME starts out as the configured FO_KEEPALIVE_TIME divided by FO_CONTACT_PER_KEEPALIVE_TIME โœจ when a CONNECT or CONNECTREPLY message comes in, the OPTION_F_KEEPALIVE_TIME option gets checked, and that value is divided by the configured FO_CONTACT_PER_KEEPALIVE_TIME to work out FO_SEND_TIME for that connection ๐Ÿงฎ it's giving precision.

each partner MUST also keep an FO_KEEPALIVE_TIMER for each failover connection ๐Ÿซถ it begins at FO_KEEPALIVE_TIME, counts down once per second, and gets reset back to FO_KEEPALIVE_TIME whenever a message arrives on that connection. if it ever reaches zero, that connection is considered dead ๐Ÿ’€ and the FO_KEEPALIVE_TIME for that connection MUST be sent to the failover partner on every CONNECT or CONNECTREPLY message, inside the OPTION_F_KEEPALIVE_TIME option ๐ŸŽ€


7. Binding Updates and Acks โœจ

7.1. Time Skew

okay, partners swap info about their known lease states ๐Ÿ”„ to compare a known lease state with an update from a partner reliably, the servers have to be able to compare the times stored in their known lease state with the times in the update, and that's a whole thing ๐Ÿ™ˆ so the failover protocol keeps it simple: the failover partners use some mechanism to sync the clocks on the two servers to within roughly 5 seconds โฑ๏ธ

a way to measure and track the relative time difference between servers is needed to make that sync happen ๐Ÿ“ every message carries the time it was sent in the sent-time field (see Section 5.2) ๐Ÿ’Œ the transmitting server MUST set that as close to the actual transmission as possible, and the receiving partner MUST store its own timestamp of reception as close to the actual reception as possible ๐Ÿ“ฅ then the received timestamp gets compared with the local one. periodt ๐Ÿ’…

7.2. Information Model

in most DHCP servers, a lease on an IPv6 address or a prefix can have several different binding-status values, sometimes called "lease states" ๐ŸŒธ no two DHCP server implementations have exactly the same set of binding-status values, but [RFC3315] enforces some shared meaning across the general semantics of the values used by different DHCP server implementations ๐Ÿงš

to send binding database updates from one server to another with the failover protocol, some common binding-status values have to be defined ๐Ÿฆ‹ it's not expected that these values match any actual DHCPv6 implementation in a DHCP server. the goal is that the binding-status values defined in this document should be convertible back and forth between these and the ones many DHCP server implementations use ๐Ÿ”

the lease binding-status values for the failover protocol are listed below ๐Ÿ“‹ unless noted otherwise, there MAY be client information attached to each of these values ๐ŸŽ€

  • ACTIVE - the lease is assigned to a client ๐Ÿ’– client identification data MUST appear.
  • EXPIRED - a client's binding on this lease has expired ๐Ÿฅ€ when the partner acks the BNDUPD message for an expired lease, the server sets its internal state to PENDING-FREE. client identification SHOULD appear.
  • RELEASED - a client sent a RELEASE message ๐Ÿ‘‹ when the partner acks the BNDUPD message for a released lease, the server sets its internal state to PENDING-FREE. client identification SHOULD appear.
  • PENDING-FREE - once a lease is expired or released, it becomes PENDING-FREE ๐ŸŒ€ depending on which algorithm allocated the lease, PENDING-FREE may mean either FREE or FREE-BACKUP. implementations don't have to implement this PENDING-FREE state, but they may switch straight to the destination state. for clarity of representation, this transitional PENDING-FREE state is treated as a separate state ๐Ÿง 
  • FREE - used when a DHCP server needs to say a lease is unused by any client, but it wasn't just released, expired, or reset by a network administrator ๐Ÿƒ when the partner acks the BNDUPD message for a FREE lease, the server marks the lease as available for assignment by the primary server. on a secondary server running in PARTNER-DOWN state, after waiting the MCLT, the lease MAY be allocated to a client by the secondary server ๐Ÿซง client identification MAY appear and, as a hint, shows the last client to have used this lease.
  • FREE-BACKUP - this lease can be allocated by the secondary server to a client at any time ๐ŸŒˆ on the primary server running in PARTNER-DOWN state, after waiting the MCLT, the lease MAY be allocated to a client by the primary server if the proportional algorithm was used. client identification MAY appear and, as a hint, shows the last client to have used this lease ๐Ÿ’œ
  • ABANDONED - the lease is considered unusable by the DHCP system ๐Ÿšซ the main reason it ends up here is receiving a DECLINE message for the lease. client identification MAY appear ๐Ÿ™…โ€โ™€๏ธ
  • RESET - the lease was made available by an operator command ๐Ÿ”ง it's a distinct state so you can tell why the lease became FREE. client identification MAY appear. โœจ

which binding-status values get a timeout is implementation dependent ๐Ÿคทโ€โ™€๏ธ some, like ACTIVE, have a timeout value in every implementation, while others, like ABANDONED, have one in some implementations and not others. in some implementations, a binding-status value may have a timeout in some circumstances and not in others ๐ŸŒ— receiving a BNDUPD message with a particular binding-status value and an OPTION_F_STATE_EXPIRATION_TIME tells you that this binding-status value is associated with a timeout โณ

the lease state machine is shown in Figure 2 ๐Ÿ—บ๏ธ most states are stationary, meaning the lease stays put until an external event triggers a move to another state. the only transitive state is PENDING-FREE, and once it's reached, the state machine immediately moves on to either FREE or FREE-BACKUP ๐Ÿƒโ€โ™€๏ธ

                               +---------+
                /------------->|  ACTIVE |<--------------\
                |              +---------+               |
                |                |  |  |                 |
                |       /--(8)--/  (3)  \--(9)-\         |
                |      |            |           |        |
                |      V            V           V        |
                |  +-------+   +--------+   +---------+  |
                |  |EXPIRED|   |RELEASED|   |ABANDONED|  |
                |  +-------+   +--------+   +---------+  |
                |      |            |            |       |
                |      |            |           (10)     |
                |      |            |            V       |
                |      |            |       +---------+  |
                |      |            |       |  RESET  |  |
                |      |            |       +---------+  |
                |      |            |            |       |
                |       \--(4)--\  (4)  /--(4)--/        |
                |                |  |  |                 |
               (1)               V  V  V                (2)
                |              /---------\               |
                |              | PENDING-|               |
                |              |  FREE   |               |
                |              \---------/               |
                |                 |   |                  |
                |         /-(5)--/     \-(6)-\           |
                |        |                    |          |
                |        V                    V          |
                |    +-------+         +-----------+     |
                \----|  FREE |<--(7)-->|FREE-BACKUP|-----/
                     +-------+         +-----------+

                          PENDING-FREE transition

Figure 2: Lease State Machine ๐ŸŒฟ

the transitions between states happen because of these events ๐Ÿ‘‡

(1) the primary server allocates a lease. ๐Ÿ 

(2) the secondary server allocates a lease. ๐Ÿก

(3) the client sends RELEASE, and the lease is released. ๐Ÿ‘‹

(4) the partner acknowledges the state change ๐Ÿค this transition MAY also happen if the server is in PARTNER-DOWN state and the MCLT has passed since it entered the RELEASED, EXPIRED, or RESET states โฐ

(5) the lease belongs to a pool governed by proportional allocation, or independent allocation is used and this lease belongs to the primary server's pool ๐Ÿ’œ

(6) the lease belongs to a pool governed by independent allocation, and the lease belongs to the secondary server ๐Ÿฉท

(7) a pool rebalance event happens (POOLREQ/POOLRESP messages get exchanged) ๐Ÿ” delegable prefixes belonging to the primary server can be assigned to the secondary server's pool (going from FREE to FREE-BACKUP), or the other way around ๐ŸŒธ

(8) the lease has expired. ๐Ÿฅ€

(9) a DECLINE message is received, or the lease is deemed unusable for other reasons ๐Ÿšซ

(10) an administrative action is taken to restore an abandoned lease to a usable state ๐Ÿ› ๏ธ this transition MAY happen because of implementation-specific handling of an ABANDONED lease ๐ŸŒˆ one possible example is a Neighbor Discovery or ICMPv6 Echo check to see if the address is still in use ๐Ÿ”

a lease that's no longer in use (because it expired or was released) becomes PENDING-FREE ๐Ÿซง depending on the allocation algorithm, that lease goes back to the primary pool (FREE) or the secondary pool (FREE-BACKUP) ๐ŸŽ€ the conditions for specific transitions are shown in Figure 3 ๐Ÿ“Š

                 +----------------+---------+-----------+
                 | \   Lease owner|         |           |
                 |  \----------\  | Primary | Secondary |
                 |Algorithm     \ |         |           |
                 +----------------+---------+-----------+
                 | Proportional   | FREE    |FREE-BACKUP|
                 | Independent    | FREE    |    FREE   |
                 +----------------+---------+-----------+

Figure 3: PENDING-FREE State Transitions ๐Ÿ’œ

7.3. Times Required for Exchanging Binding Updates โฐ

okay so each server has to keep track of these specific times on top of the ones the base DHCP spec [RFC3315] already asks for ๐Ÿ’…

  • expiration-time: the greatest lifetime this server has ever acked to its failover partner in a BNDREPLY message.
  • acked-partner-lifetime: the greatest lifetime the failover partner has ever acked to this server in a BNDREPLY message.
  • partner-lifetime: the time value that will be sent (or that has been sent) to the partner to show the time after which the partner can consider the lease expired. When a BNDUPD message comes in, this value can get updated from the received OPTION_F_EXPIRATION_TIME. ๐Ÿ”ฅ
  • client-last-transaction-time: the time this server most recently interacted with the client tied to this lease.
  • partner-raw-clt-time: the time the partner most recently interacted with the client tied to this lease. This time stays exactly as it was received by this server and MUST NOT be adjusted in any way. ๐Ÿ™ˆ
  • start-time-of-state: the time the binding-status of this lease changed to its current value.
  • state-expiration-time: the time the current state of this lease will expire.

7.4. Sending Binding Updates ๐Ÿ“ค

every BNDUPD message is about either (1) a single client binding inside an OPTION_CLIENT_DATA option that includes IAADDR or IAPREFIX options tied to that client, or (2) a single prefix lease in an OPTION_IAPREFIX option for prefixes that aren't currently tied to any clients. it's giving organized ๐Ÿ—‚๏ธ

All information about a particular client binding MUST be contained in a single OPTION_CLIENT_DATA option (see Section 4.1.2.2 of [RFC5007]). The OPTION_CLIENT_DATA option holds at least the data below in its client-options section:

  • OPTION_CLIENTID containing the DUID of the client most recently associated with this lease MUST appear.
  • OPTION_LQ_BASE_TIME containing the absolute time that the information was placed in this OPTION_CLIENT_DATA option (see Section 6.3.1 of [RFC7653]) MUST appear.
  • OPTION_VSS (see Section 3.4 of [RFC6607]). This option MUST NOT appear if the information in this OPTION_CLIENT_DATA option is associated with the global, default VPN. This option MUST appear if the information in this OPTION_CLIENT_DATA option is associated with a VPN other than the global, default VPN. Support of [RFC6607] is not required, and if it is not supported, then an OPTION_VSS MUST NOT appear. If [RFC6607] is supported, then an OPTION_VSS MUST appear if and only if a VPN other than the global, default VPN is used. ๐ŸŒธ
  • OPTION_F_RECONFIGURE_DATA containing the time and reconfigure key, if any.
  • OPTION_LQ_RELAY_DATA containing information described in Section 4.1.2.4 of [RFC5007], if any exists.
  • OPTION_IA_NA or OPTION_IA_TA for an IPv6 address, or OPTION_IA_PD for an IPv6 prefix. More than one of either of these options MAY appear if more than one of them are associated with this client. At least one of an OPTION_IA_NA, OPTION_IA_TA, or OPTION_IA_PD must appear.
    • IAID: the Identity Association used by the client while obtaining a given lease. Note that (1) one client can use many IAIDs at the same time and (2) IAIDs for OPTION_IA_NA, OPTION_IA_TA, and OPTION_IA_PD are orthogonal number spaces. ๐Ÿงš
    • T1 time sent to client.
    • T2 time sent to client.
    • Inside of the IA_NA-options, IA_TA-options, or IA_PD-options sections:
      • OPTION_IAADDR for an IPv6 address or an OPTION_IAPREFIX for an IPv6 prefix MUST appear.
        • IPv6 address or IPv6 prefix (with length).
        • Preferred lifetime sent to client.
        • Valid lifetime sent to client.
        • Inside of the IAaddr-options or IAprefix-options:
          • OPTION_F_BINDING_STATUS containing the binding-status MUST appear.
          • OPTION_F_START_TIME_OF_STATE containing the start-time-of-state MUST appear.
          • OPTION_F_STATE_EXPIRATION_TIME (absolute) containing the state-expiration-time*.
          • OPTION_CLT_TIME (relative) containing the client-last-transaction-time. See [RFC5007] for a description of this option.
          • OPTION_F_PARTNER_LIFETIME (absolute) containing the partner-lifetime*.
          • OPTION_F_PARTNER_RAW_CLT_TIME (absolute) containing the partner-raw-clt-time.
          • OPTION_F_EXPIRATION_TIME (absolute) containing the expiration-time*.
          • OPTION_CLIENT_FQDN containing the FQDN information associated with this lease and client, if any.

Information about a prefix lease is contained in a single OPTION_IAPREFIX option. Only a single OPTION_IAPREFIX option may appear in a BNDUPD message outside of an OPTION_CLIENT_DATA option. In detail:

  • OPTION_IAPREFIX for a prefix lease.
    • IPv6 prefix (with length).
    • Inside of the IAprefix-options section:
      • OPTION_VSS (see Section 3.4 of [RFC6607]). This option MUST NOT appear if the information in this OPTION_IAPREFIX option is associated with the global, default VPN. This option MUST appear if the information in this OPTION_IAPREFIX option is associated with a VPN other than the global, default VPN. Support of [RFC6607] is not required, and if it is not supported, then an OPTION_VSS MUST NOT appear. If [RFC6607] is supported, then an OPTION_VSS MUST appear if and only if a VPN other than the global, default VPN is used.
      • OPTION_LQ_BASE_TIME containing the absolute time that this information was placed in this OPTIONS_IAPREFIX option (see Section 6.3.1 of [RFC7653]) MUST appear.
      • OPTION_F_BINDING_STATUS containing the binding-status MUST appear.
      • OPTION_F_START_TIME_OF_STATE containing the start-time-of-state MUST appear.
      • OPTION_F_STATE_EXPIRATION_TIME (absolute) containing the state-expiration-time*.
      • OPTION_F_PARTNER_LIFETIME (absolute) containing the partner-lifetime*.
      • OPTION_F_EXPIRATION_TIME (absolute) containing the expiration-time*.

Items marked with a single asterisk (*) MUST appear only if the value in the OPTION_F_BINDING_STATUS is associated with a timeout; otherwise, it MUST NOT appear. See Section 7.2 for details. โณ

The OPTION_CLT_TIME MUST, if it appears, be the time that the server last interacted with the DHCP client. It MUST NOT be, for instance, the time that the lease expired if there has been no interaction with the DHCP client in question. ๐Ÿ•

A server SHOULD be prepared to clean up DNS information once the lease expires or is released. See Section 9 for a detailed discussion about DNS update. ๐Ÿงน

Another reason the partner may be interested in keeping additional data is to enable better support for Leasequery [RFC5007], Bulk Leasequery [RFC5460], or Active Leasequery [RFC7653], some of which feature queries based on Relay-ID, link address, or Remote-ID. ๐Ÿ”

7.5. Receiving Binding Updates ๐Ÿ“ฅ

7.5.1. Monitoring Time Skew ๐Ÿ•ต๏ธโ€โ™€๏ธ

The sent-time from the failover message is compared with the current time of the receiving server as recorded when it received the message. The difference is noted, and if it is greater than 5 seconds the receiving server SHOULD drop the connection. A message SHOULD be logged to signal the reason for the connection being dropped. ๐Ÿšซ

Any time can be before, after, or essentially the same as another time. Any time that ends up being +/- 5 seconds of another time SHOULD be considered to be representing the same time when performing a comparison between two times. ๐Ÿ’ญ

7.5.2. Acknowledging Reception ๐Ÿซถ

Upon acceptance of a binding update, the server MUST notify its partner that it has processed the binding update (and updated its lease state database if necessary) by sending a BNDREPLY message. A server MUST NOT send the BNDREPLY message before its binding database is updated. โœ…

7.5.3. Processing Binding Updates ๐Ÿงฉ

When a BNDUPD message is received, it MUST contain either a single OPTION_CLIENT_DATA option or a single OPTION_IAPREFIX option.

When analyzing a BNDUPD message from a partner server, if there is insufficient information in the BNDUPD message to process it, then it is rejected with an OPTION_STATUS_CODE of "MissingBindingInformation". ๐Ÿ™…โ€โ™€๏ธ

The server receiving a BNDUPD message from its partner must evaluate the received information in each OPTION_CLIENT_DATA or IAPREFIX option to see if it is consistent with the server's already-known state and, if it is not, decide to accept or reject the information. Section 7.5.4 provides details regarding how the server makes this determination. ๐Ÿ‘‘

A server receiving a BNDUPD message MUST respond to the sender of that message with a BNDREPLY message that contains the same transaction-id as the BNDUPD message. This BNDREPLY message MUST contain either a single OPTION_CLIENT_DATA option or a single OPTION_IAPREFIX option, corresponding to whatever was received in the BNDUPD message. ๐Ÿ’Œ

An OPTION_CLIENT_DATA option or an OPTION_IAPREFIX option in the BNDREPLY message that is accepted SHOULD NOT contain an OPTION_STATUS_CODE unless a status message needs to be sent to the failover partner, in which case it SHOULD include an OPTION_STATUS_CODE option with a status-code indicating success and whatever message is needed. ๐ŸŽ€

To indicate rejection of the information in an OPTION_CLIENT_DATA option or an OPTION_IAPREFIX option, an OPTION_STATUS_CODE SHOULD be included with a status-code indicating an error in the OPTION_CLIENT_DATA option or OPTION_IAPREFIX option in the BNDREPLY message. ๐Ÿ’…โœจ

7.5.4. Accept or Reject? ๐ŸŽ€

Okay bestie, the first job when you get an OPTION_CLIENT_DATA option or OPTION_IAPREFIX option is to pull out the client info (if there is any) and the lease info, then go look up the address lease or prefix lease in the server's binding database. ๐Ÿ’…

If an OPTION_VSS option shows up inside the OPTION_CLIENT_DATA or OPTION_IAPREFIX option and the VPN it names isn't in the receiving server's configuration, reject the whole OPTION_CLIENT_DATA or OPTION_IAPREFIX option by including an OPTION_STATUS_CODE option with a status-code of "ConfigurationConflict". Not it, no thank you ๐Ÿ™…โ€โ™€๏ธ

If the lease in the OPTION_CLIENT_DATA or OPTION_IAPREFIX option isn't one that belongs to the failover endpoint that got the OPTION_CLIENT_DATA option, reject it with an OPTION_STATUS_CODE option that has a status-code of "ConfigurationConflict". Wrong house, sis ๐Ÿ 

Generally, whether you accept or reject comes down to comparing two time values. One is from the OPTION_CLIENT_DATA or OPTION_IAPREFIX option in the BNDUPD message. The other is from the receiving server's binding database for the address or prefix lease that showed up in the BNDUPD message. For a BNDUPD message where the OPTION_F_BINDING_STATUS is ACTIVE, EXPIRED, or RELEASED, the time is the OPTION_CLT_TIME if one shows up, or the OPTION_F_START_TIME_OF_STATE if it doesn't. For any other binding-status value, the time for the BNDUPD message is the later of (1) the OPTION_CLT_TIME if one shows up or (2) the OPTION_F_START_TIME_OF_STATE. The time for the lease in the server's binding database is the client-last-transaction-time if one shows up, or the start-time-of-state if it doesn't. โฐ

The basic move is to compare these times. If the one from the BNDUPD message is clearly later, accept the info in the OPTION_CLIENT_DATA or OPTION_IAPREFIX option. If the one in the server's binding database is clearly later, reject the info in the BNDUPD message. The drama happens when they're basically the same (i.e., +/- 5 seconds). In that case they're treated as identical, even with the tiny differences. Figure 4 has a table with the rules for all of these situations. ๐Ÿ“Š

                      binding-status in received OPTION_CLIENT_DATA
                                                 or OPTION_IAPREFIX
binding-status in
receiving server's                                 FREE        RESET
lease state DB   ACTIVE   EXPIRED   RELEASED   FREE-BACKUP  ABANDONED
---------------------------------------------------------------------
ACTIVE           accept(3) time(1)   accept     time(1)      accept
EXPIRED          accept    accept    accept     accept       accept
RELEASED         accept    accept    accept     accept       accept
FREE/FREE-BACKUP accept    accept    accept     accept       accept
RESET            time(2)   accept    accept     accept       accept
ABANDONED        accept    accept    accept     accept       accept

                   Figure 4: Conflict Resolution

Here's what each rule means:

  • accept: If the time value in the OPTION_CLIENT_DATA or OPTION_IAPREFIX option is later than the time value in the server's binding database, accept it. Otherwise, reject it. ๐Ÿซถ
  • time(1): If the current time is later than the receiving server's state-expiration-time, accept it. Otherwise, reject it. โณ
  • time(2): If the OPTION_CLT_TIME value (if it appears) in the OPTION_CLIENT_DATA is later than the start-time-of-state in the receiving server's binding, accept it. Otherwise, reject it. ๐Ÿงš
  • accept,time(1),time(2): If rejecting, use a status-code of "OutdatedBindingInformation". ๐Ÿ™ˆ
  • accept(3): If the clients in an OPTION_CLIENT_DATA option and in a receiving server's binding are different, then if time(2) holds or the receiving server is a secondary, accept it. Otherwise, reject it with a status-code of "AddressInUse". If the clients match, accept the update. ๐Ÿ‘ฏโ€โ™€๏ธ

The lease update may be accepted or rejected. If a lease gets rejected with "OutdatedBindingInformation", then the flag in the lease that says the partner should be updated with the info in this lease SHOULD be set. Otherwise, it SHOULD NOT be changed. If that flag wasn't set before, an update MAY be sent to the partner right away (though the BNDREPLY to this BNDUPD message SHOULD be sent first). If the flag was already set, an update SHOULD NOT be sent to the partner right away. Instead, the update goes out during the next periodic scan, not immediately. This stops a possible update storm if the servers can't agree. In the end, the server with the most recent binding info should have its update accepted by its partner. ๐ŸŒธ


7.5.5. Accepting Updates โœจ

When the info in an OPTION_CLIENT_DATA or OPTION_IAPREFIX option gets accepted, some of it gets stored in the receiving server's binding database, and a matching OPTION_CLIENT_DATA or OPTION_IAPREFIX option goes into a BNDREPLY message. What goes into that option in the BNDREPLY message is described in Section 7.6. ๐Ÿ’Œ

Here's how the info in an accepted OPTION_CLIENT_DATA option gets stored in the receiving server's binding database:

  1. The OPTION_CLIENTID is used to find the client.
  2. The other data in the top level of the OPTION_CLIENT_DATA option is stored with the client as appropriate.
  3. For each of the OPTION_IA_NA, OPTION_IA_TA, or OPTION_IA_PD options in the OPTION_CLIENT_DATA option, and for each of the OPTION_IAADDR or OPTION_IAPREFIX options in the IA_* options:
    • a. OPTION_F_BINDING_STATUS is stored as the binding-status.
    • b. OPTION_F_PARTNER_LIFETIME is stored in the expiration-time.
    • c. OPTION_F_STATE_EXPIRATION_TIME is stored in the state-expiration-time.
    • d. OPTION_CLT_TIME [RFC5007] is stored in the partner-raw-clt-time.
    • e. OPTION_F_PARTNER_RAW_CLT_TIME replaces the client-last-transaction-time if it is later than the current client-last-transaction-time.
    • f. OPTION_F_EXPIRATION_TIME replaces the partner-lifetime if it is later than the current partner-lifetime.

Now for an accepted single OPTION_IAPREFIX option that isn't inside an OPTION_CLIENT_DATA option. It gets stored in the receiving server's binding database like this:

  1. The IPv6 prefix is used to find the prefix.
  2. Inside of the IAprefix-options section:
    • a. OPTION_F_BINDING_STATUS is stored as the binding-status.
    • b. OPTION_F_PARTNER_LIFETIME (if any) is stored in the expiration-time.
    • c. OPTION_F_STATE_EXPIRATION_TIME (if any) is stored in the state-expiration-time.
    • d. OPTION_F_EXPIRATION_TIME (if any) replaces the partner-lifetime if it is later than the current partner-lifetime.

7.6. Sending Binding Replies

okay bestie, servers have to be SO responsive ๐Ÿ’… A server MUST respond to every BNDUPD message with a BNDREPLY message. The BNDREPLY message MUST contain an OPTION_CLIENT_DATA option if the BNDUPD message contained an OPTION_CLIENT_DATA option, or it MUST contain an OPTION_IAPREFIX option if the BNDUPD message contained an OPTION_IAPREFIX option. The BNDREPLY message MUST have the same transaction-id as the BNDUPD message it's responding to ๐ŸŽ€

Acceptance or rejection of all of a BNDUPD message, or of a particular part of it, gets signaled with an OPTION_STATUS_CODE option โœจ An OPTION_STATUS_CODE option with an error status-code is significant ๐Ÿ”ฅ But an OPTION_STATUS_CODE option whose status-code means success is just informational. It doesn't change how the BNDREPLY gets processed when the server that sent the BNDUPD receives it ๐Ÿฆ‹

Rejection of all of or part of the info in a BNDUPD message is signaled in a BNDREPLY by using the OPTION_STATUS_CODE with an error in the status-code field. This rejection can happen at either of two levels, the top of the option hierarchy or the bottom of it ๐ŸŒˆ

  1. Entire BNDUPD: The OPTION_STATUS_CODE with an error is present in the outermost option of the BNDREPLY, which is either the single OPTION_CLIENT_DATA option or the single OPTION_IAPREFIX option. An example of this sort of error might be that an OPTION_VSS option was present and specified a VPN that might not exist on the receiving server ๐Ÿ’€
  2. Single address or prefix: The OPTION_STATUS_CODE with an error is present in a single IAADDR or IAPREFIX option that's itself contained in an OPTION_IA_NA, OPTION_IA_TA, or OPTION_IA_PD option. An example of this might be that a particular IPv6 address was specified in an IAADDR option that isn't in the receiving server's configuration ๐Ÿ™ˆ

Rejection at either of these levels means the whole option (including any other options inside it) gets rejected, wherever the error-carrying OPTION_STATUS_CODE option shows up. The reverse isn't true though! An OPTION_STATUS_CODE with success does NOT mean everything inside was accepted ๐Ÿ‘‘

If the BNDREPLY message contains an OPTION_CLIENT_DATA option, then that OPTION_CLIENT_DATA option MUST contain at least the data below in its client-options section:

  • OPTION_CLIENTID containing the DUID of the client most recently associated with this IPv6 address.
  • OPTION_VSS from the BNDUPD message, if any.
  • OPTION_IA_NA or OPTION_IA_TA for an IPv6 address, or OPTION_IA_PD for an IPv6 prefix. More than one of either of these options MAY appear if there's more than one of them associated with this client ๐Ÿงš
    • Inside of the IA_NA-options, IA_TA-options, or IA_PD-options sections:
      • OPTION_IAADDR for an IPv6 address or an OPTION_IAPREFIX for an IPv6 prefix.
        • IPv6 address or IPv6 prefix (with length).
        • Inside of the IAaddr-options or IAprefix-options:
          • OPTION_STATUS_CODE containing an error code, or containing a success code if a message is required. An OPTION_STATUS_CODE option SHOULD NOT appear with a success code unless a message tied to that success code needs to be included. No OPTION_STATUS_CODE option at all means success ๐Ÿซถ
          • OPTION_F_BINDING_STATUS containing the binding-status received in the BNDUPD message.
          • OPTION_F_STATE_EXPIRATION_TIME (absolute) containing the state-expiration-time received in the BNDUPD message.
          • OPTION_F_PARTNER_LIFETIME_SENT (absolute) containing a duplicate of the OPTION_F_PARTNER_LIFETIME received in the BNDUPD message.

If the BNDREPLY message contains a single OPTION_IAPREFIX option that is NOT contained in an OPTION_CLIENT_DATA option, then that OPTION_IAPREFIX option MUST contain at least the data below:

  • IPv6 prefix (with length).
  • IAprefix-options:
    • OPTION_VSS from the BNDUPD message, if any.
    • OPTION_STATUS_CODE containing an error code, or containing a success code if a message is required. If the info in the matching OPTION_IAPREFIX in the BNDUPD message was accepted and no status message was required (the usual case!), no OPTION_STATUS_CODE option appears โœจ
    • OPTION_F_BINDING_STATUS containing the binding-status received in the BNDREPLY message.
    • OPTION_F_STATE_EXPIRATION_TIME (absolute) containing the state-expiration-time received in the BNDREPLY message.
    • OPTION_F_PARTNER_LIFETIME_SENT (absolute) containing a duplicate of the OPTION_F_PARTNER_LIFETIME received in the BNDREPLY message.

7.7. Receiving Binding Acks

When a BNDREPLY message comes in, the overall OPTION_CLIENT_DATA option or the overall OPTION_IAPREFIX option might contain an OPTION_STATUS_CODE with an error. That's a rejection of the entire BNDUPD message ๐Ÿ˜ญ An enclosed OPTION_IA_NA, OPTION_IA_TA, or OPTION_IA_PD option might also carry an OPTION_STATUS_CODE with an error, meaning everything in that containing option got rejected. Or an individual IAADDR or IAPREFIX option might have an OPTION_STATUS_CODE with an error, meaning just that IAADDR or IAPREFIX got rejected. An OPTION_STATUS_CODE with a success code has no bearing on acceptance at any level of the BNDREPLY message ๐ŸŒธ

Receiving a rejection (or a rejected part of a BNDREPLY message) requires no processing at all, other than remembering that you saw it ๐Ÿง 

The info in a BNDREPLY message inside an OPTION_CLIENT_DATA that represents an acceptance gets stored with the right client and lease, like this:

  1. The OPTION_CLIENTID is used to find the client.
  2. For each of the OPTION_IA_NA, OPTION_IA_TA, or OPTION_IA_PD options in the OPTION_CLIENT_DATA option, and for each of the OPTION_IAADDR or OPTION_IAPREFIX options they contain:
    • a. OPTION_F_PARTNER_LIFETIME_SENT is stored in the acked-partner-lifetime.
    • b. The partner-lifetime is set to 0 to indicate that no more information needs to be sent to the partner ๐Ÿฆ‹

Alternatively, the BNDREPLY message may contain a single OPTION_IAPREFIX option that is NOT contained in an OPTION_CLIENT_DATA option, representing info about a single prefix lease. If the IAprefix-options section of that OPTION_IAPREFIX option contains an OPTION_STATUS_CODE representing an error, it's considered a rejection of the matching BNDUPD message. If the OPTION_IAPREFIX option doesn't contain an OPTION_STATUS_CODE option, or if its OPTION_STATUS_CODE option has a success status, then these three items get stored in the lease state database, in the section for the prefix lease the OPTION_IAPREFIX option represents ๐Ÿ’œ

  1. OPTION_F_BINDING_STATUS containing the binding-status received in the BNDREPLY message.
  2. OPTION_F_STATE_EXPIRATION_TIME (absolute) containing the state-expiration-time received in the BNDREPLY message.
  3. OPTION_F_PARTNER_LIFETIME_SENT (absolute) containing a duplicate of the OPTION_F_PARTNER_LIFETIME received in the BNDREPLY message.

7.8. BNDUPD/BNDREPLY Data Flow

okay this part is a whole vibe ๐ŸŒˆ Figure 5 shows how the times from Section 7.3 connect to the options that carry them. It also relates the times on one failover partner to the times on the other failover partner โœจ

----------------------- BNDUPD ---------------------------------

  Source on            OPTION_F in            Storage on
 Sending Server  ->   BNDUPD message   ->   Receiving Server


                                 [always update]

partner-lifetime      PARTNER_LIFETIME      expiration-time

client-last-transaction-time  CLT_TIME      partner-raw-clt-time
start-time-of-state   START_TIME_OF_STATE   start-time-of-state
state-expiration-time STATE_EXPIRATION_TIME state-expiration-time

                           [update only if received > current]

expiration-time       EXPIRATION_TIME       partner-lifetime
partner-raw-clt-time  PARTNER_RAW_CLT_TIME
                                       client-last-transaction-time

----------------------- BNDREPLY -------------------------------

  Storage on            OPTION_F in           Storage on
 Receiving Server <-   BNDUPD message   <-   Sending Server

        [always update]

acked-partner-lifetime PARTNER_LIFETIME_SENT duplicate of received
                                               PARTNER_LIFETIME
(nothing to update)    STATE_EXPIRATION_TIME state-expiration-time

----------------------------------------------------------------

             Figure 5: BNDUPD and BNDREPLY Time Handling

8. Endpoint States

8.1. State Machine Operation โœจ

Okay so every server (or, more accurately, failover endpoint) can be in a bunch of different failover states ๐Ÿฆ‹ These states are lowkey the boss of what a server does when a DHCP client sends a request, and how it reacts when stuff outside changes (like losing its connection to its failover partner) ๐Ÿ’…

The failover state a server is running in controls these behaviors:

  • Responsiveness: the server is either responsive to DHCP client requests, renew responsive, or unresponsive.
  • Allocation Pool: which pool of addresses (or prefixes) can be used for advertisement when a SOLICIT comes in, or for allocation when a REQUEST, RENEW, or REBIND message comes in.
  • MCLT: valid lifetimes have to stay within what the partner has acked plus the MCLT (unless the failover state doesn't require this restriction) ๐Ÿซถ

A server moves from one failover state to another based on the values of these state variables:

  • Current failover state.
  • Communications status ("OK" or not "OK").
  • Partner's failover state (if known).

Whenever any of the state variables above change, the state machine gets invoked, and that might trigger a change in the current failover state ๐Ÿ”ฅ So whenever the communications status changes, the state machine processing kicks off. This may or may not actually change the current failover state, so don't panic lol ๐Ÿ˜ญ

Whenever a server switches to a new failover state, the new state MUST be communicated to its failover partner in a STATE message if the communications status is "OK". On top of that, whenever a server enters a new state, it MUST record the new state, its current understanding of its partner's state, and the time it entered the new state in stable storage ๐Ÿ’œ

The state transition diagram below (Figure 6) is the condensed, bestie-friendly version of the state machine ๐ŸŒธ If anything in the text describing a particular state doesn't match what Figure 6 shows, the text should be considered authoritative. Keep that in mind, periodt โœจ

In Figure 6, the terms "responsive", "r-responsive", and "unresponsive" show up in the states and refer to whether the server in that state is allowed to be responsive, renew responsive, or unresponsive. The "+", "-", or "" in the upper right corner of each state tells you whether communication with the other server is ongoing: "+" means communications are "OK", "-" means communications are interrupted, and "" means communications may be either "OK" or interrupted ๐Ÿ“

    +---------------+  V  +--------------+
    |    RECOVER  * |  |  |   STARTUP  - |
    |(unresponsive) |  +->+(unresponsive)|
    +------+--------+     +--------------+
    +-Comm. OK             +-----------------+
    |     Other State:     |  PARTNER-DOWN - +<---------------------+
    |    RESOLUTION-INTER. | (responsive)    |                      ^
   All     POTENTIAL-      +----+------------+                      |
  Others   CONFLICT------------ | --------+                         |
    |      CONFLICT-DONE     Comm. OK     |     +--------------+    |
 UPDREQ or                 Other State:   |  +--+ RESOLUTION - |    |
 UPDREQALL                  |       |     |  |  | INTERRUPTED  |    |
 Rcv UPDDONE             RECOVER    All   |  |  | (responsive) |    |
    |  +---------------+    |      Others |  |  +------+-----+-+    |
    +->+RECOVER-WAIT * | RECOVER-   |     |  |         ^     |      |
       |(unresponsive) |  WAIT or   |     |  Comm.     |    Ext.    |
       +-----------+---+  DONE      |     |  OK     Comm.   Cmd---->+
Comm.---+     Wait MCLT     |       V     V  V     Failed           |
Changed |          V    +---+   +---+-----+--+-+       |            |
 |  +---+----------++   |       | POTENTIAL  + +-------+            |
 |  |RECOVER-DONE * |  Wait     | CONFLICT     +------+             |
 +->+(unresponsive) |  for      |(unresponsive)|   Primary          |
    +------+--------+  Other  +>+----+--------++   resolve    Comm. |
     Comm. OK          State: |      |        ^    conflict  Changed|
+---Other State:-+   RECOVER- |   Secondary   |       V       V   | |
|    |           |     DONE   |   resolve     |  +----+-------+--++ |
| All Others:  POTENT.  |     |   conflict    |  |CONFLICT-DONE * | |
| Wait for    CONFLICT--|-----+      |        |  | (responsive)   | |
| Other State:          V            V        |  +-------+--------+ |
| NORMAL or RECOVER-   ++------------+---+    | Other State: NORMAL |
| |       DONE      |     NORMAL    + +<--------------+          |
| |    +--+----------+-->+ pri: responsive +-------External Command-->+
| |       ^          ^   |sec: r-responsive|    |                     |
| |       |          |   +--------+--------+    |                     |
| |       |          |            |             |                     |
| |   Wait for   Comm. OK  Comm. Failed         |             External
| |    Other      Other           |             |             Command
| |    State:     State:     Start Auto         |                or
| | RECOVER-DONE  NORMAL    Partner Down     Comm. OK         Auto
| |       |     COMM.-INT.      Timer       Other State:       Partner
| |    Comm. OK      |            V          All Others         Down
| |   Other State:   |  +---------+--------+    |            expiration
| |     RECOVER      +--+ COMMUNICATIONS - +----+                     |
| |       +-------------+   INTERRUPTED    |                          |
RECOVER               |  (responsive)    +------------------------->+
RECOVER-WAIT--------->+------------------+

Figure 6: Failover Endpoint State Machine ๐Ÿงš

8.2. State Machine Initialization ๐ŸŽ€

The state machine is characterized by storage (in stable storage) of at least the following info:

  • Current failover state.
  • Previous failover state.
  • Start time of current failover state.
  • Partner's failover state.
  • Start time of partner's failover state.
  • Time most recent message received from partner.

The state machine gets initialized by reading these data items from stable storage and restoring their values from what was saved. If there's no info in stable storage about these items, then they should be initialized like this:

  • Current failover state: Primary: PARTNER-DOWN, Secondary: RECOVER.
  • Previous failover state: None.
  • Start time of current failover state: Current time.
  • Partner's failover state: None until reception of STATE message.
  • Start time of partner's failover state: None until reception of STATE message.
  • Time most recent message received from partner: None until message received.

8.3. STARTUP State ๐Ÿงšโ€โ™€๏ธ

The STARTUP state is basically a chance for a server to probe its partner before it starts serving DHCP clients ๐Ÿ’– While in STARTUP, a server tries to learn its partner's state and figure out (using that info, if it's available) what state it should enter next.

The STARTUP state doesn't have any specific transitions drawn in the state machine diagram (Figure 6). That's because the processing during STARTUP can push the server into any of the other states, so drawing specific arcs would just clutter things up ๐Ÿ™ˆ

8.3.1. Operation in STARTUP State ๐Ÿ’…

The server MUST NOT be responsive to DHCP clients in STARTUP state. ๐Ÿšซ

Whenever a STATE message is sent to the partner while in STARTUP state, the STARTUP flag MUST be set in the OPTION_F_SERVER_FLAGS option, and the previously recorded failover state MUST be placed in the OPTION_F_SERVER_STATE option. Both of these options are included in the STATE message ๐Ÿ‘‘

8.3.2. Transition out of STARTUP State ๐Ÿšชโœจ

okay so this is the part where the server finally wakes up and decides what its life is going to be, bestie ๐Ÿ’… the algorithm below runs every single time the server initializes itself and enters STARTUP state, no cap ๐Ÿซถ

two variables do all the heavy lifting here ๐ŸŽ€. PREVIOUS-STATE is basically just a storage spot for a state ๐Ÿงš, while CURRENT-STATE is the main character ๐Ÿ‘‘ because it not only stores the current state but also actually changes the failover endpoint's state to whatever is set in it. iconic behavior honestly ๐Ÿ˜ญ

Step 1: first the server checks stable storage for any record of a previous failover state ๐Ÿ“. If there's a record, PREVIOUS-STATE gets set to the last recorded value and TIME-OF-FAILURE gets set to the time the server failed (or a time beyond which the server could not have been operating) and then we go to Step 2 ๐Ÿ’–. If there's no record, PREVIOUS-STATE becomes RECOVER and TIME-OF-FAILURE becomes 0 ๐ŸŒธ. This lets two servers that already have lease info sync up before they do anything, which is so wholesome ๐Ÿฅบ

now here's the lowkey tricky bit ๐Ÿ™ˆ. Sometimes an existing server gets commissioned as a failover server and brought back online while its partner isn't available yet. In that case the newly commissioned failover server won't operate until its partner shows up, but it still has DHCP server responsibilities anyway ๐Ÿ’€. To handle this, a server SHOULD be configurable so it can move directly into PARTNER-DOWN state after the startup period expires if it couldn't reach its partner during startup โœจ. not me giving this server a backup plan ๐Ÿ˜ญ๐Ÿซถ

Step 2: implementations really do differ on how they handle the failover endpoint state machine ๐Ÿฆ‹. A lot of the time, state transitions happen when communications go from "OK" to failed (or failed to "OK"), and some implementations bake part of their state machine processing around those changes ๐ŸŒˆ.

so during startup, if PREVIOUS-STATE is a state where communications were "OK", PREVIOUS-STATE gets set to the state you land in after the communication failed transition from that state, if one exists ๐Ÿ’…. Some states don't have a communication failed transition at all, since they allow both "communications OK" and "failed" ๐Ÿ™ˆ

Step 3: start the STARTUP state timer โฐ. How long a server stays in STARTUP (without hearing from its partner) is implementation dependent, but it SHOULD be short ๐Ÿ’œ. It SHOULD also be long enough for a TCP connection to a heavily loaded partner to get created across a slow network, bc that's just realistic ๐Ÿข๐ŸŒธ

Step 4: if the server is a primary server, it attempts to create a TCP connection to the failover partner ๐Ÿ”ฅ. If it's a secondary server, it listens on the failover port and waits for the primary server to connect ๐Ÿ‘‘. See Section 6.1 for the deets ๐Ÿ“–โœจ

Step 5: wait for "communications OK" ๐Ÿซถ. When and if communications become "OK", the server clears the STARTUP flag and sets CURRENT-STATE to PREVIOUS-STATE ๐ŸŽ€

now the drama ๐Ÿ˜ญ. If the partner is in PARTNER-DOWN state, and the time it entered PARTNER-DOWN (as received in the OPTION_F_START_TIME_OF_STATE option in the STATE message) is later than the last recorded time of operation of this server, then CURRENT-STATE becomes RECOVER ๐ŸŒˆ. If the time it entered PARTNER-DOWN is earlier than the last recorded time of operation of this server, then CURRENT-STATE becomes POTENTIAL-CONFLICT ๐Ÿ’€

then we transition to CURRENT-STATE and take the "communications OK" state transition based on the CURRENT-STATE of this server and the partner ๐Ÿ’–

Step 6: if the startup time expires before communications become "OK", the server SHOULD transition to PREVIOUS-STATE ๐Ÿงšโœจ


8.4. PARTNER-DOWN State ๐ŸŒ™

PARTNER-DOWN state is a state either server can enter ๐Ÿฆ‹. When a server is in this state, it assumes it's the only one operating and serving the client base ๐Ÿ‘‘. If one server is in PARTNER-DOWN state, the other server MUST NOT be operating ๐Ÿšซ๐Ÿ’…

a server can enter PARTNER-DOWN state for either (1) operator intervention (when an operator determines the partner is, indeed, down) or (2) an optional auto-partner-down capability, where PARTNER-DOWN state gets entered automatically after the server has been in COMMUNICATIONS-INTERRUPTED state for a predetermined period of time โฐ๐ŸŽ€

8.4.1. Operation in PARTNER-DOWN State ๐ŸŒธ

The server MUST be responsive in PARTNER-DOWN state, regardless of whether it's primary or secondary ๐Ÿซถ

it will allow renewal of all outstanding leases ๐Ÿ’–

for delegable prefixes, the server allocates leases from its own pool ๐Ÿ“. After a fixed period of time (the MCLT interval) has elapsed from entry into PARTNER-DOWN state, it MAY allocate delegable prefixes from the set of all available pools ๐Ÿฆ‹. The server MUST fully deplete its own pool before starting allocations from its downed partner's pool ๐Ÿ’…

IPv6 addresses that are available for independent allocation by the other server (upon entering PARTNER-DOWN state) SHOULD NOT be allocated to a client ๐Ÿ™ˆ. If one elects to do so anyway, they MUST NOT be allocated to a new client until the MCLT beyond the entry into PARTNER-DOWN state has elapsed ๐Ÿ’€

a server in PARTNER-DOWN state MUST NOT allocate a lease to a DHCP client different from the client it was allocated to at the time of entry into PARTNER-DOWN state, until the MCLT beyond the maximum of the following times has passed: client expiration time, most recently transmitted partner-lifetime, most recently received ack of the partner-time from the partner, and most recently acked partner-lifetime to the partner ๐Ÿ˜ญ. If this time would be earlier than the current time plus the MCLT, then the time the server entered PARTNER-DOWN state plus the MCLT is used instead ๐ŸŒˆ

the server is not restricted by the MCLT when offering valid lifetimes while in PARTNER-DOWN state ๐ŸŽ€

in the unlikely case that two servers are operating in PARTNER-DOWN state, there's a chance duplicate leases for the same prefix could get assigned ๐Ÿ’€. This leads to a POTENTIAL-CONFLICT (unresponsive) state when the servers reestablish contact ๐Ÿฅบ. This duplicate-lease issue can be prevented as long as the server grants new leases from its own pool, so the server operating in PARTNER-DOWN state MUST use its own pool first for new leases before assigning any leases from its downed partner's pool ๐Ÿ‘‘โœจ

8.4.2. Transition out of PARTNER-DOWN State ๐Ÿฆ‹

when a server in PARTNER-DOWN state succeeds in establishing a connection to its partner, its actions depend on the state and flags received in the STATE message from the other server as part of establishing the connection ๐Ÿ’–

if the STARTUP bit is set in the OPTION_F_SERVER_FLAGS option of a received STATE message, a server in PARTNER-DOWN state MUST NOT take any state transitions based on reestablishing communications ๐Ÿšซ. If a server is in PARTNER-DOWN state, it ignores all STATE messages from its partner that have the STARTUP bit set in the OPTION_F_SERVER_FLAGS option ๐Ÿ™ˆ

if the STARTUP bit is not set in the OPTION_F_SERVER_FLAGS option of a STATE message received from its partner, then a server in PARTNER-DOWN state takes the following actions, based on the partner's state as received in a STATE message (either right after establishing communications or any time later when a new state is received) ๐ŸŒธ:

  • if the partner is in NORMAL, COMMUNICATIONS-INTERRUPTED, PARTNER-DOWN, POTENTIAL-CONFLICT, RESOLUTION-INTERRUPTED, or CONFLICT-DONE state, then transition to POTENTIAL-CONFLICT state ๐Ÿ’€
  • if the partner is in RECOVER or RECOVER-WAIT state, then stay in PARTNER-DOWN state ๐Ÿงš
  • if the partner is in RECOVER-DONE state, then transition to NORMAL state โœจ

8.5. RECOVER State ๐ŸŒˆ

this state indicates that the server has no information in its stable storage, or that it's reintegrating with a server in PARTNER-DOWN state after it has been down ๐Ÿฅบ. A server in this state MUST attempt to refresh its stable storage from the other server ๐Ÿ’…

8.5.1. Operation in RECOVER State ๐ŸŽ€

the server MUST NOT be responsive in RECOVER state ๐Ÿšซ

a server in RECOVER state will attempt to reestablish communications with the other server ๐Ÿซถ

8.5.2. Transition out of RECOVER State โœจ

okay so if the other server is already in POTENTIAL-CONFLICT, RESOLUTION-INTERRUPTED, or CONFLICT-DONE when the connection comes back, the server in RECOVER just moves itself to POTENTIAL-CONFLICT. ๐Ÿซฃ

if the other server is in literally any other state, then the RECOVER server asks for any missing binding info by sending an UPDREQ message. but if it figures out it lost its stable storage (it has no record of ever talking to its partner, even though the partner does remember talking to it) ๐Ÿ˜ญ, it MUST send an UPDREQALL message instead. otherwise it MUST send an UPDREQ message. ๐Ÿ’…

then it waits for an UPDDONE message, and once that lands it moves to RECOVER-WAIT state. bestie, that's the glow-up ๐Ÿฆ‹

if communication fails while the server is getting the results of its UPDREQ or UPDREQALL, it stays in RECOVER state and just reissues that same message once communications are back. no drama, just retry ๐Ÿซถ

if UPDDONE doesn't show up within an implementation-dependent amount of time and no BNDUPD messages are coming in either, the connection SHOULD be dropped. ๐Ÿ’€

                   A                                        B
                 Server                                  Server

                   |                                        |
                RECOVER                               PARTNER-DOWN
                   |                                        |
                   | >--UPDREQ-------------------->         |
                   |                                        |
                   |        <---------------------BNDUPD--< |
                   | >--BNDREPLY------------------>         |
                  ...                                      ...
                   |                                        |
                   |        <---------------------BNDUPD--< |
                   | >--BNDREPLY------------------>         |
                   |                                        |
                   |        <--------------------UPDDONE--< |
                   |                                        |
              RECOVER-WAIT                                  |
                   |                                        |
                   | >--STATE-(RECOVER-WAIT)------>         |
                   |                                        |
                   |                                        |
          Wait MCLT from last known                         |
             time of failover operation                     |
                   |                                        |
              RECOVER-DONE                                  |
                   |                                        |
                   | >--STATE-(RECOVER-DONE)------>         |
                   |                                     NORMAL
                   |        <-------------(NORMAL)-STATE--< |
                NORMAL                                      |
                   | >---- State-(NORMAL)--------------->   |
                   |                                        |
                   |                                        |

Figure 7: Transition out of RECOVER State ๐ŸŽ€

and if communication drops at any point while a server is in RECOVER state, it just stays put. once comms are restored, it starts the transition out of RECOVER state all over again. the comeback era ๐ŸŒˆ

8.6. RECOVER-WAIT State ๐Ÿงš

this state means the server has sent an UPDREQ or UPDREQALL and got the UPDDONE saying it has every outstanding binding update. ๐Ÿ™Œ now it waits out the MCLT, so any processing it did before losing its stable storage can't cause problems later. patience is a whole aesthetic ๐Ÿ•ฐ๏ธ

8.6.1. Operation in RECOVER-WAIT State ๐Ÿ™ˆ

the server MUST NOT be responsive in RECOVER-WAIT state. silence is giving protection ๐Ÿค

8.6.2. Transition out of RECOVER-WAIT State ๐ŸŒธ

the second it enters RECOVER-WAIT, the server MUST start a timer. that timer is set to expire at the time the server went down (the TIME-OF-FAILURE from Section 8.3.2) if that's known, or the time the server started if the TIME-OF-FAILURE is unknown, plus the MCLT. when the timer goes off, the server moves into RECOVER-DONE state. โฐ

this gives any IPv6 addresses or prefixes that the server handed out before losing its client binding info in stable storage a chance to reach the other server or just time out. ๐Ÿซง

if the server has never run failover before, there's no need to wait around, and it MAY move straight to RECOVER-DONE state. ๐Ÿƒโ€โ™€๏ธ but figuring out whether it's run failover before is vital, so the info from the partner has to be used, since this server's stable storage may have been lost. big brain move ๐Ÿง 

if communication fails while a server is in RECOVER-WAIT state, nothing changes for this state. the server SHOULD keep its timer running, and if the timer expires while communications are down, the server SHOULD move to RECOVER-DONE state. this is rare, since failover transitions usually don't happen while comms are interrupted, but there's no reason to block it here ๐Ÿคทโ€โ™€๏ธ


8.7. RECOVER-DONE State ๐Ÿ’–

this state exists so one server can make an interlocked transition out of RECOVER state while its partner goes from PARTNER-DOWN or COMMUNICATIONS-INTERRUPTED into NORMAL state. it's like a choreographed group dance, everybody hits the move at the same time ๐Ÿ’ƒ

8.7.1. Operation in RECOVER-DONE State ๐Ÿซถ

a server in RECOVER-DONE state SHOULD be renew responsive, and it MAY respond to RENEW requests. but it MUST only change the state of a lease that shows up in the RENEW request. it MUST NOT allocate any additional leases while in RECOVER-DONE state, and it should only respond to RENEW requests for leases it already has a record of. boundaries, but make them cute ๐ŸŽ€

8.7.2. Transition out of RECOVER-DONE State ๐Ÿฆ‹

when a server in RECOVER-DONE figures out that its partner has entered NORMAL or RECOVER-DONE state, it moves into NORMAL state too. ๐Ÿฅณ

if the partner enters RECOVER or RECOVER-WAIT state, this server transitions to COMMUNICATIONS-INTERRUPTED. ๐Ÿซ 

if the partner enters POTENTIAL-CONFLICT state, this server enters POTENTIAL-CONFLICT state as well. we're in this together ๐Ÿค

if communication fails while in RECOVER-DONE state, the server just stays in RECOVER-DONE state. ๐Ÿ’ค


8.8. NORMAL State ๐Ÿ‘‘

NORMAL state is the main-character state. it's where a server is talking to the other server and any required resynchronization is already done. some binding database sync still happens in NORMAL state, but potential conflicts get sorted out before entering it, and so does binding database data loss. the glow-up is complete โœจ

when a server enters NORMAL state, it sends its partner every binding update that hasn't been acknowledged yet, as BNDUPD messages. ๐Ÿ“จ

once all that is done, if the server entering NORMAL state is a secondary server, it requests delegable prefixes for allocation using the POOLREQ message. ๐Ÿ“

8.8.1. Operation in NORMAL State ๐Ÿ’…

the primary server is responsive in NORMAL state. the secondary is renew responsive in NORMAL state. ๐ŸŒท

when a primary server is in NORMAL state, it operates like this:

Valid lifetime calculations ๐Ÿงฎ As discussed in Section 4.4, the lease interval given to a DHCP client can never be more than the MCLT greater than the most recently acknowledged partner lifetime received from the failover partner or the current time, whichever is later.

As long as a server sticks to this constraint, the specifics of the lease interval it gives to a DHCP client, or the value of the partner lifetime it sends to its failover partner, are implementation dependent. ๐Ÿค“

Lazy update of partner server ๐Ÿฆฅ After sending a REPLY that includes a lease update to a client, the server servicing that DHCP client request tries to update its partner with the new binding info. see Section 4.3. ๐Ÿ’Œ

Reallocation of leases between clients ๐Ÿ” whenever a client binding is released or expires, a BNDUPD message must be sent to the partner, setting the binding state to RELEASED or EXPIRED. but until a BNDREPLY comes back for that message, the lease can't be given to another client. it can't go back to the same client again if a BNDUPD message was sent, otherwise it can. see Section 4.2.2.1 for details. ๐Ÿ”’

in NORMAL state, each server gets binding updates from its partner in BNDUPD messages (see Section 7.5.5). it records them in its binding database in stable storage, and then sends a matching BNDREPLY message back to its partner (see Section 7.6). ๐Ÿ“ฌ

8.8.2. Transition out of NORMAL State ๐Ÿšช

if a server in NORMAL state gets an external command saying its partner is down, it transitions immediately into PARTNER-DOWN state. this is usually a rare situation, where some outside agency knew the partner was down before the failover server figured it out on its own. ๐Ÿ“ฃ

if a server in NORMAL state doesn't get acks for messages sent to its partner within an implementation-dependent period of time, it MAY move into COMMUNICATIONS-INTERRUPTED state. this could happen if the partner can keep the TCP connection alive and can send CONTACT messages on a schedule, but for some reason can't process BNDUPD messages. ๐Ÿซฅ

if it's determined that communications are not "OK" (as defined in Section 6.6), then the server should transition into COMMUNICATIONS-INTERRUPTED state. ๐Ÿ“ต

if a server in NORMAL state gets any message from its partner showing the partner has changed state in a way the server didn't expect, the server should transition into COMMUNICATIONS-INTERRUPTED state and take the appropriate transition from there. for example, the partner going from POTENTIAL-CONFLICT into NORMAL state is expected, but the partner going from NORMAL state into POTENTIAL-CONFLICT is not. ๐Ÿ™ƒ

if a server in NORMAL state receives a DISCONNECT message from its partner, then the server should transition into COMMUNICATIONS-INTERRUPTED state. ๐Ÿ‘‹


8.9. COMMUNICATIONS-INTERRUPTED State ๐ŸŒช๏ธ

a server goes into COMMUNICATIONS-INTERRUPTED state whenever it can't talk to its partner. primary and secondary servers cycle automatically (no admin needed) between NORMAL state and COMMUNICATIONS-INTERRUPTED state as the network connection between them fails and recovers, or as the partner server goes between working and not working. no duplicate lease allocation can happen while the servers are cycling between these states, so it's still safe ๐Ÿ›ก๏ธ

when a server enters COMMUNICATIONS-INTERRUPTED state, if it's been configured to automatically transition out of COMMUNICATIONS-INTERRUPTED state and into PARTNER-DOWN state (i.e., auto-partner-down has been configured), then a timer starts for the length of the configured auto-partner-down period. โณ

a server transitioning into the COMMUNICATIONS-INTERRUPTED state from the NORMAL state SHOULD raise an alarm condition to alert administrative staff to a potential problem in the DHCP subsystem. ๐Ÿšจ

8.9.1. Operation in COMMUNICATIONS-INTERRUPTED State โœจ

okay so in this state, a server MUST respond to all DHCP client requests ๐Ÿ’– When it's handing out brand new leases, each server pulls from its own pool. The primary MUST allocate only FREE delegable prefixes, and the secondary MUST allocate only FREE-BACKUP delegable prefixes. Each server also uses its own independent IPv6 address ranges ๐Ÿฆ‹

When it comes to RENEW messages, each server will still let a client keep renewing its current lease, even if the other server originally gave that lease out ๐Ÿซถ Just know the renewal period MUST NOT go past the MCLT beyond the later of (1) the partner lifetime already acknowledged by the other server or (2) now ๐Ÿ’…

But here's the tea ๐Ÿต since the server can't talk to its partner in this state, the acknowledged partner lifetime won't get updated, even though RENEW processing keeps going ๐Ÿ˜ญ That's likely to eventually make the actual lifetimes converge to the MCLT (unless that's greater than the desired lease time, which would be unusual) ๐ŸŒธ

Meanwhile, the server should keep trying to set up a connection with its partner ๐Ÿงš

8.9.2. Transition out of COMMUNICATIONS-INTERRUPTED State

If the auto-partner-down timer expires while a server is in COMMUNICATIONS-INTERRUPTED state, it will go straight into PARTNER-DOWN state โฐ

If a server in COMMUNICATIONS-INTERRUPTED state gets an external command telling it that its partner is down, it will transition immediately into PARTNER-DOWN state ๐Ÿ’€

If communications with the other server are restored, then the server in COMMUNICATIONS-INTERRUPTED state will transition into another state based on what state the partner is in:

  • NORMAL or COMMUNICATIONS-INTERRUPTED: Transition into NORMAL state.
  • RECOVER: Stay in COMMUNICATIONS-INTERRUPTED state.
  • RECOVER-DONE: Transition into NORMAL state.
  • PARTNER-DOWN, POTENTIAL-CONFLICT, CONFLICT-DONE, or RESOLUTION-INTERRUPTED: Transition into POTENTIAL-CONFLICT state.

Figure 8 shows the transition from NORMAL state to COMMUNICATIONS-INTERRUPTED state and then back to NORMAL state again ๐Ÿฆ‹

          Primary                                Secondary
           Server                                  Server

            NORMAL                                  NORMAL
              | >--CONTACT------------------->         |
              |        <--------------------CONTACT--< |
              |         [TCP connection broken]        |
         COMMUNICATIONS-         :              COMMUNICATIONS-
           INTERRUPTED           :                INTERRUPTED
              |      [attempt new TCP connection]      |
              |         [connection succeeds]          |
              |                                        |
              | >--CONNECT------------------->         |
              |        <---------------CONNECTREPLY--< |
              | >--STATE--------------------->         |
              |                                     NORMAL
              |        <-------------------STATE-----< |
            NORMAL                                     |
              |                                        |
              | >--BNDUPD-------------------->         |
              |        <-------------------BNDREPLY--< |
              |                                        |
              |        <---------------------BNDUPD--< |
              | >------BNDREPLY-------------->         |
             ...                                      ...
              |                                        |
              |        <--------------------POOLREQ--< |
              | >--POOLRESP------------------>         |
              |                                        |
              | >--BNDUPD-(#1)--------------->         |
              |        <-------------------BNDREPLY--< |
              |                                        |
              | >--BNDUPD-(#2)--------------->         |
              |        <-------------------BNDREPLY--< |
              |                                        |

Figure 8: Transition from NORMAL State to COMMUNICATIONS-INTERRUPTED State and Back

8.10. POTENTIAL-CONFLICT State ๐ŸŒˆ

This state says the two servers are trying to reintegrate with each other, but at least one of them was running in a state that didn't guarantee automatic reintegration would be possible ๐Ÿฅบ In POTENTIAL-CONFLICT state, the servers may find out that the same lease has been offered and accepted by two different clients ๐Ÿ˜ฌ

A goal of the failover protocol is to make it as unlikely as possible that POTENTIAL-CONFLICT state is ever entered ๐ŸŽ€

When a primary server enters POTENTIAL-CONFLICT state, it should request that the secondary send it all updates the primary server hasn't acknowledged yet, by sending an UPDREQ message to the secondary server ๐Ÿ’Œ

A secondary server entering POTENTIAL-CONFLICT state will wait for the primary to send it an UPDREQ message ๐Ÿซง

8.10.1. Operation in POTENTIAL-CONFLICT State

Any server in POTENTIAL-CONFLICT state MUST NOT process any incoming DHCP requests ๐Ÿšซ๐Ÿ™ˆ

8.10.2. Transition out of POTENTIAL-CONFLICT State

If communication with the partner fails while in POTENTIAL-CONFLICT state, then the server will transition to RESOLUTION-INTERRUPTED state ๐Ÿ’”

Whenever either server receives an UPDDONE message from its partner while in POTENTIAL-CONFLICT state, it MUST transition to a new state ๐Ÿ”ฅ The primary MUST transition to CONFLICT-DONE state, and the secondary MUST transition to NORMAL state. This means the primary leaves POTENTIAL-CONFLICT state before the secondary does ๐Ÿ‘‘ It's because the primary sends an UPDREQ message and receives an UPDDONE message before the secondary sends its own UPDREQ message and receives its UPDDONE message โœจ

When a secondary server receives an indication that the primary server has moved from POTENTIAL-CONFLICT to CONFLICT-DONE state, it SHOULD send an UPDREQ message to the primary server ๐Ÿฆ‹

          Primary                                Secondary
          Server                                  Server

            |                                        |
      POTENTIAL-CONFLICT                    POTENTIAL-CONFLICT
            |                                        |
            | >--UPDREQ-------------------->         |
            |                                        |
            |        <---------------------BNDUPD--< |
            | >--BNDREPLY------------------>         |
           ...                                      ...
            |                                        |
            |        <---------------------BNDUPD--< |
            | >--BNDREPLY------------------>         |
            |                                        |
            |        <--------------------UPDDONE--< |
      CONFLICT-DONE                                  |
            | >--STATE--(CONFLICT-DONE)---->         |
            |        <---------------------UPDREQ--< |
            |                                        |
            | >--BNDUPD-------------------->         |
            |        <-------------------BNDREPLY--< |
           ...                                      ...
            | >--BNDUPD-------------------->         |
            |        <-------------------BNDREPLY--< |
            |                                        |
            | >--UPDDONE------------------->         |
            |                                     NORMAL
            |        <------------STATE--(NORMAL)--< |
         NORMAL                                      |
            | >--STATE--(NORMAL)----------->         |
            |                                        |
            |        <--------------------POOLREQ--< |
            | >------POOLRESP-------------->         |
            |                                        |

Figure 9: Transition out of POTENTIAL-CONFLICT State

8.11. RESOLUTION-INTERRUPTED State ๐Ÿฅ€

This state says the two servers were trying to reintegrate in POTENTIAL-CONFLICT state, but communication failed before reintegration finished ๐Ÿ˜ต

The RESOLUTION-INTERRUPTED state exists because servers aren't responsive in POTENTIAL-CONFLICT state. If one server drops out while both are in POTENTIAL-CONFLICT state, the one still in service can't process DHCP client requests, so there's no DHCP server left to handle them ๐Ÿ˜ญ RESOLUTION-INTERRUPTED is the state a server moves to if its partner disappears while it's in POTENTIAL-CONFLICT state ๐Ÿซ 

When a server enters RESOLUTION-INTERRUPTED state, it SHOULD raise an alarm condition to alert administrative staff of a problem in the DHCP subsystem ๐Ÿšจ

8.11.1. Operation in RESOLUTION-INTERRUPTED State

In this state, a server MUST respond to all DHCP client requests ๐Ÿ’– When allocating new leases, each server SHOULD allocate from its own pool (if that can be determined). The primary SHOULD allocate only FREE leases, and the secondary SHOULD allocate only FREE-BACKUP leases ๐ŸŽ€ When responding to renewal requests, each server will let a client keep renewing its current lease, whether or not the receiving server gave that lease out. The renewal period still MUST NOT exceed the MCLT beyond the later of (1) the partner lifetime already acknowledged by the other server or (2) now ๐Ÿ’…

But since the server can't communicate with its partner in this state, the acknowledged partner lifetime won't be updated in any new bindings ๐Ÿ™ˆ

8.11.2. Transition out of RESOLUTION-INTERRUPTED State

If a server in RESOLUTION-INTERRUPTED state receives an external command telling it that its partner is down, it will transition immediately into PARTNER-DOWN state ๐Ÿ’€

If communications with the other server are restored, then the server in RESOLUTION-INTERRUPTED state will transition into POTENTIAL-CONFLICT state ๐Ÿฆ‹

8.12. CONFLICT-DONE State ๐Ÿ“

This state says that while the two servers were reintegrating, the primary server got all the updates from the secondary server. It moves into CONFLICT-DONE state so it can be totally responsive to the client load ๐Ÿงš There's no operational difference between CONFLICT-DONE and NORMAL for the primary server, since both states answer all clients' requests. The split between CONFLICT-DONE and NORMAL states only matters in case a load-balancing extension is ever defined ๐ŸŒธ

8.12.1. Operation in CONFLICT-DONE State

A primary server in CONFLICT-DONE state is fully responsive to all DHCP clients (kind of like the situation in COMMUNICATIONS-INTERRUPTED state) ๐Ÿ’…

If communication fails, remain in CONFLICT-DONE state. If communication becomes "OK", remain in CONFLICT-DONE state until the conditions for transition out of CONFLICT-DONE state are satisfied โœจ

8.12.2. Transition out of CONFLICT-DONE State

If communication with the partner fails while in CONFLICT-DONE state, then the server will remain in CONFLICT-DONE state ๐Ÿซถ

When a primary server determines that the secondary server has moved into NORMAL state, the primary server will also transition into NORMAL state ๐Ÿ‘‘

9. DNS Update Considerations โœจ

Okay bestie, so DHCP servers (and clients) can do "DNS update" like it's described in [RFC2136] (RFC 2136 [RFC2136]) to keep DNS name mappings up to date while they handle DHCP leases ๐Ÿฆ‹ There are lots of different admin setups for DHCP-DNS integration, and [RFC4704] (RFC 4704 [RFC4704]) walks through several of them and gives the guidelines that DHCP servers and clients should follow when they set each one up ๐Ÿ’…

The failover protocol creates some DNS update drama that doesn't exist in non-failover setups ๐Ÿ˜ญ This section breaks down those issues and defines the info failover partners need to swap so they stay consistent. Just so you know, having this section does NOT mean every DHCPv6 failover implementation has to support DNS updates ๐Ÿ™ˆ

The whole point here is to clear up where the failover and DHCP DNS update protocols overlap, for implementations that do both. It's not adding a new rule to DHCPv6 failover, promise ๐Ÿซถ So a DHCP server that does failover MAY also support DNS updates, but if it does, it SHOULD use the techniques described here so it can split the updates correctly between the failover partners. For how DHCP servers handle potential conflicts when updating DNS even without failover, check out [RFC4704] (RFC 4704 [RFC4704]) and [RFC4703] (RFC 4703 [RFC4703]) ๐ŸŒธ

From the failover protocol's point of view, there's no real reason a server using DNS update to update a DNS server can't be partnered with a server that doesn't use DNS update ๐Ÿงš Still, a server that can't support DNS update, or isn't configured to, SHOULD output a warning message when it gets BNDUPD messages saying its failover partner is set up to do DNS update. An implementation MAY treat that as an error and refuse the BNDUPD message by returning the status DNSUpdateNotSupported in an OPTION_STATUS_CODE option in the BNDREPLY message. Or it MAY just keep going and warn the admin somehow ๐Ÿ‘€

9.1. Relationship between Failover and DNS Update

The failover protocol lays out when each failover server can renew a lease for its current DHCP client, and when it can grant a lease to a brand new client ๐Ÿ’œ Similar rules decide when a failover server should start a DNS update and when it should try to remove records from DNS. The failover protocol's rules are built around the external behavior they want: no duplicate address or prefix assignments, clients keep using leases they got from one partner even if they can only reach the other partner, and the secondary DHCP server can still hand out new leases even when it can't reach the primary ๐ŸŽ€ The DNS update behavior for DHCPv6 failover servers is supposed to match that same energy:

  1. Allow timely DNS updates from the server that grants a lease to a client. Know that there's usually a DNS update "lifecycle" that mirrors the DHCP lease lifecycle ๐Ÿ’– This will likely include adding records when the lease is granted, and removing the DNS records when the lease is later made available to a different client.
  2. Share enough info between the two failover servers so one can finish the DNS update lifecycle even if the other server originally granted the lease ๐Ÿซถ
  3. Avoid redundant or overlapping DNS updates where both failover servers are trying to do DNS updates for the same lease-client binding ๐Ÿ™…โ€โ™€๏ธ
  4. Avoid situations where one partner is trying to add resource records (RRs) related to a lease binding while the other partner is trying to remove RRs related to that same lease binding ๐Ÿ’€

DHCPv6 servers set up for DNS update usually do these operations on both the AAAA and the PTR RRs, but that's not required ๐ŸŒˆ A DHCPv6 server could totally be set up to only update DNS with PTR records, while the DHCPv6 clients handle their own AAAA records. In that case, everything in this discussion only applies to the PTR records ๐Ÿฆ‹

9.2. Exchanging DNS Update Information

For either server to finish a DNS update, or to remove DNS records its partner added, both servers have to know the FQDN tied to the lease-client binding ๐Ÿ“ Plus, to handle DNS updates properly, some extra info is needed too. All of the following info needs to be sent between the failover partners:

  1. The FQDN that the client asked to be associated with the lease. If the client doesn't ask for a particular FQDN and the failover server makes one up, or if the failover server is set up to swap out a client-requested FQDN for a different one, then the server-generated value gets used ๐Ÿงš
  2. The FQDN that actually ended up in DNS for this lease. It might be different from the client-requested FQDN because of some kind of disambiguation or other DHCP server config (as described above) โœจ
  3. The status of any DNS update operations that are in progress or done ๐Ÿ”ฅ
  4. Enough info to let the failover partner remove the FQDN from DNS, if that ever becomes necessary ๐Ÿ˜ญ

These data items are the bare minimum needed so two failover partners can reliably share the job of keeping DNS up to date with the leases given out to clients ๐Ÿ‘‘

This info would normally ride along in BNDUPD messages sent from one failover partner to the other ๐Ÿ’… Failover servers MAY choose not to include it in BNDUPD messages if nothing has changed about the status of any DNS update tied to the lease ๐Ÿ™ˆ

The partner server that receives BNDUPD messages with DNS update info SHOULD compare the status info and the FQDN against the DNS update info it already has for that lease binding, and update its own idea of the DNS update status to match ๐Ÿซถ

Some implementations just send a BNDUPD message without waiting for the DNS update to finish, then send a second BNDUPD message once it does ๐ŸŒธ Other implementations hold off on sending the partner a BNDUPD message until the DNS server has acknowledged the DNS update, or until some time limit has passed, so they can avoid sending a second one ๐Ÿฆ‹

The FQDN option contains the FQDN that will be tied to the AAAA RR (if the server is doing a AAAA RR update for the client) ๐Ÿ’– The PTR RR can be generated automatically from the IPv6 address value. The FQDN can be put together in a few different ways, depending on server config and what the client sent in its DHCP messages ๐ŸŽ€ The client might supply a hostname it wants the server to use when forming the FQDN, or it might supply the whole FQDN. The server might be set up to try using whatever the client supplies, it might be configured with an FQDN to use for that client, or it might be set up to synthesize one ๐Ÿงš

Here's a plot twist ๐Ÿ˜ญ The server talking to the client might not have finished the DNS update when it sends the first BNDUPD message about the lease binding. So the FQDN in later BNDUPD messages may not match the FQDN in earlier ones ๐Ÿ’€ For example, the responsive server might be set up to handle cases where two or more DHCP client FQDNs are identical, by changing the most-specific label in some of those FQDNs to try to make them unique (a process sometimes called "disambiguation") ๐Ÿ™ˆ Or, at sites that use some or all of the info clients supply to form the FQDN, a client's config might change so it starts sending new data โœจ The server talking to the client may then react by removing the DNS records it originally added for that client and replacing them with records that point to the client's new FQDN ๐Ÿ”ฅ In cases like this, the server SHOULD include the actual FQDN that was used in subsequent DNS update options in any BNDUPD messages exchanged between the failover partners. This server SHOULD also include relevant info in its BNDUPD messages ๐Ÿ‘‘ That info may be needed so the non-responsive partner can detect client config changes that alter the hostname or FQDN data the client includes in its DHCPv6 requests ๐Ÿ’œ

9.3. Adding RRs to the DNS

A failover server that's going to do DNS updates SHOULD start the DNS update when it grants a new lease to a client ๐Ÿฆ‹ The server that did NOT grant the lease SHOULD NOT start a DNS update when it receives the BNDUPD message after the lease has been granted. The failover protocol makes sure only one partner grants a lease to any individual client, so this rule keeps both partners from starting updates at the same time ๐Ÿซถ The server starting the update SHOULD follow the protocol in [RFC4704] (RFC 4704 [RFC4704]). The server MAY be configured to do a AAAA RR update on behalf of its clients, or not ๐ŸŒˆ Normally, a failover server won't start DNS updates when it renews leases. There are two cases, though, where a failover server MAY start a DNS update when it renews a lease for its existing client ๐Ÿ’…

  1. When the lease was granted before the server was configured to do DNS updates, the server MAY be configured to perform updates when it next renews existing leases ๐Ÿงš
  2. If a server is in PARTNER-DOWN state, it can conclude that its partner is no longer trying to do an update for the existing client ๐Ÿ˜ญ If the remaining server hasn't recorded that an update for the binding was successfully completed, the server MAY start a DNS update. It can start this update right away when it enters PARTNER-DOWN state, it can do it in the background, or it can start the update the next time it hears from the DHCP client ๐Ÿ”ฅ

Note that, no matter whether failover is in use, there's a real use case for updating DNS on every lease renewal ๐Ÿ“ If there's worry that the info in DNS doesn't match the info in the DHCP server, updating DNS on lease renewal is one way to gradually make sure DNS matches what the DHCP server has ๐Ÿ’–

9.4. Deleting RRs from the DNS ๐Ÿ—‘๏ธ

okay bestie, deleting DNS records is its own little drama ๐Ÿ’€ The failover server that makes a lease PENDING-FREE SHOULD initiate any DNS deletes if it has recorded that DNS records were added on behalf of the client.

A server that is not in PARTNER-DOWN state "makes a lease PENDING-FREE" when it starts a BNDUPD message with a binding-status of FREE, FREE-BACKUP, EXPIRED, or RELEASED ๐ŸŽ€ Its partner confirms that status by acking the BNDUPD, and once the server gets the BNDREPLY, it has officially "made the lease PENDING-FREE" โœจ The other way around is different: a server in PARTNER-DOWN state "makes a lease PENDING-FREE" when it sets the binding-status to FREE, because in PARTNER-DOWN state no communication with the partner is needed at all ๐Ÿฆ‹

This is the moment it should kick off the DNS operations that delete RRs from the DNS. Its partner SHOULD NOT start DNS deletes for the DNS records tied to that lease binding as part of sending the BNDREPLY ๐Ÿ™ˆ The partner MAY have sent BNDUPD messages with a binding-status of FREE, EXPIRED, or RELEASED before, but the other server would have rejected those BNDUPD messages, so it's all good ๐Ÿ’…

The failover protocol makes sure that only one of the two partner servers can make a lease PENDING-FREE ๐Ÿ”ฅ That server might be doing it while it's chatting in NORMAL state with its partner, or it might already be in PARTNER-DOWN state. If a server is in PARTNER-DOWN state, it may be doing DNS deletes for RRs that its partner originally added. Honestly that's iconic, because it lets one remaining partner server take over all of the DNS update work the two servers were sharing ๐Ÿ‘‘

Another thing: no DNS RR deletes will happen while either server is in COMMUNICATIONS-INTERRUPTED state ๐Ÿ’œ That's because no leases get moved into the PENDING-FREE state during that time, so there's nothing to delete yet.

A failover server SHOULD make sure that if a server fails while it's making a lease PENDING-FREE and starting a DNS delete, the lease doesn't end up with an RR still sitting in the DNS and nothing recorded in the lease state database to trigger the delete ๐Ÿงš Nobody wants a zombie record lurking around, periodt โœจ

9.5. Name Assignment with No Update of DNS ๐ŸŒธ

Sometimes a DHCP server is set up to give a client a name but NOT put that name into the DNS ๐Ÿ™ˆ It's usually a name the server found or made up from info it got from the client. In that case, this name information SHOULD be shared with the failover partner, even if it's just so the partner returns the same name if it ends up being the server the DHCP client talks to next. Main character consistency ๐ŸŽ€

10. Security Considerations ๐Ÿ”

Okay, this part is serious, so let's go ๐Ÿ’… DHCPv6 failover is an extension of standard DHCPv6, so all the security considerations from Section 23 of [RFC3315] and Section 15 of [RFC3633] that relate to the server apply here.

Using TCP adds some extra worries ๐Ÿ˜ญ Attacks that try to drain the DHCP server's TCP connection resources can stop legitimate partners from getting service. Bad actors who manage to open connections and then send invalid messages, partial messages, or no messages at all can also eat up a server's pool of available connections.

DHCPv6 failover can run in secure or insecure mode ๐Ÿงš Secure mode (using Transport Layer Security (TLS) [RFC5246]) makes sense when the TCP connection between failover partners is open to outside monitoring or interception. Insecure mode should only be used when the TCP connection between failover partners stays inside a set of protected systems. The details of those protections are out of scope for this document. Failover servers MUST use the approach documented in Section 9.1 of [RFC7653] to decide whether or not to use TLS when connecting with the failover partner ๐Ÿ”’

The threats from failover mirror the threats from DHCPv6 itself ๐Ÿ’€ That means information leaking through monitoring, and disruption of address assignment and configuration. Watching the failover TCP connection doesn't give anyone more data than they could already get by watching the interactions between DHCPv6 clients and the DHCPv6 server. Messing with the data flow between failover servers doesn't open up any new ways to disrupt address assignment and configuration either, beyond what a counterfeit DHCP server could already do. Protecting against both threats is easier than with basic DHCPv6, since only a single TCP connection needs protecting. So either use secure mode to protect that connection, or make sure it can only exist between a set of protected systems ๐Ÿซถ

When running in secure mode, TLS is what secures the connection ๐Ÿ’– The recommendations in [RFC7525] SHOULD be followed when negotiating a TLS connection.

Servers SHOULD offer configuration parameters that limit where incoming connections can come from, by validating and using the digital certificates presented to set up a TLS connection โœจ They SHOULD also limit the number of connections they accept and limit how long an idle connection can stay open ๐Ÿ•ฐ๏ธ

Authentication for DHCPv6 messages [RFC3315] MUST NOT be used to try to secure the transmission of the messages described in this document ๐Ÿšซ If you want authentication, secure mode using TLS SHOULD be used as described in Sections 8.2 and 9.1 of [RFC7653] ๐ŸŽ€

11. IANA Considerations ๐Ÿ“‹

Here's what IANA assigned, bestie ๐ŸŒˆ IANA has assigned values for the following new DHCPv6 message types in the registry maintained at <http://www.iana.org/assignments/dhcpv6-parameters>:

  • BNDUPD (24)
  • BNDREPLY (25)
  • POOLREQ (26)
  • POOLRESP (27)
  • UPDREQ (28)
  • UPDREQALL (29)
  • UPDDONE (30)
  • CONNECT (31)
  • CONNECTREPLY (32)
  • DISCONNECT (33)
  • STATE (34)
  • CONTACT (35)

IANA has assigned values for the following new DHCPv6 option codes in the registry maintained at <http://www.iana.org/assignments/dhcpv6-parameters>:

  • OPTION_F_BINDING_STATUS (114)
  • OPTION_F_CONNECT_FLAGS (115)
  • OPTION_F_DNS_REMOVAL_INFO (116)
  • OPTION_F_DNS_HOST_NAME (117)
  • OPTION_F_DNS_ZONE_NAME (118)
  • OPTION_F_DNS_FLAGS (119)
  • OPTION_F_EXPIRATION_TIME (120)
  • OPTION_F_MAX_UNACKED_BNDUPD (121)
  • OPTION_F_MCLT (122)
  • OPTION_F_PARTNER_LIFETIME (123)
  • OPTION_F_PARTNER_LIFETIME_SENT (124)
  • OPTION_F_PARTNER_DOWN_TIME (125)
  • OPTION_F_PARTNER_RAW_CLT_TIME (126)
  • OPTION_F_PROTOCOL_VERSION (127)
  • OPTION_F_KEEPALIVE_TIME (128)
  • OPTION_F_RECONFIGURE_DATA (129)
  • OPTION_F_RELATIONSHIP_NAME (130)
  • OPTION_F_SERVER_FLAGS (131)
  • OPTION_F_SERVER_STATE (132)
  • OPTION_F_START_TIME_OF_STATE (133)
  • OPTION_F_STATE_EXPIRATION_TIME (134)

IANA has assigned values for the following new DHCPv6 status codes in the registry maintained at <http://www.iana.org/assignments/dhcpv6-parameters>:

  • AddressInUse (16)
  • ConfigurationConflict (17)
  • MissingBindingInformation (18)
  • OutdatedBindingInformation (19)
  • ServerShuttingDown (20)
  • DNSUpdateNotSupported (21)
  • ExcessiveTimeSkew (22)

12. References ๐Ÿ“š

12.1. Normative References

[RFC1035]  Mockapetris, P., "Domain names - implementation and
           specification", STD 13, RFC 1035, DOI 10.17487/RFC1035,
           November 1987, <http://www.rfc-editor.org/info/rfc1035>.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <http://www.rfc-editor.org/info/rfc2119>.

[RFC2136]  Vixie, P., Ed., Thomson, S., Rekhter, Y., and J. Bound,
           "Dynamic Updates in the Domain Name System (DNS UPDATE)",
           RFC 2136, DOI 10.17487/RFC2136, April 1997,
           <http://www.rfc-editor.org/info/rfc2136>.

[RFC3315]  Droms, R., Ed., Bound, J., Volz, B., Lemon, T., Perkins,
           C., and M. Carney, "Dynamic Host Configuration Protocol
           for IPv6 (DHCPv6)", RFC 3315, DOI 10.17487/RFC3315,
           July 2003, <http://www.rfc-editor.org/info/rfc3315>.

[RFC3633]  Troan, O. and R. Droms, "IPv6 Prefix Options for Dynamic
           Host Configuration Protocol (DHCP) version 6", RFC 3633,
           DOI 10.17487/RFC3633, December 2003,
           <http://www.rfc-editor.org/info/rfc3633>.

[RFC4703]  Stapp, M. and B. Volz, "Resolution of Fully Qualified
           Domain Name (FQDN) Conflicts among Dynamic Host
           Configuration Protocol (DHCP) Clients", RFC 4703,
           DOI 10.17487/RFC4703, October 2006,
           <http://www.rfc-editor.org/info/rfc4703>.

[RFC4704]  Volz, B., "The Dynamic Host Configuration Protocol for
           IPv6 (DHCPv6) Client Fully Qualified Domain Name (FQDN)
           Option", RFC 4704, DOI 10.17487/RFC4704, October 2006,
           <http://www.rfc-editor.org/info/rfc4704>.

[RFC5007]  Brzozowski, J., Kinnear, K., Volz, B., and S. Zeng,
           "DHCPv6 Leasequery", RFC 5007, DOI 10.17487/RFC5007,
           September 2007, <http://www.rfc-editor.org/info/rfc5007>.

[RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
           (TLS) Protocol Version 1.2", RFC 5246,
           DOI 10.17487/RFC5246, August 2008,
           <http://www.rfc-editor.org/info/rfc5246>.

[RFC5460]  Stapp, M., "DHCPv6 Bulk Leasequery", RFC 5460,
           DOI 10.17487/RFC5460, February 2009,
           <http://www.rfc-editor.org/info/rfc5460>.

[RFC6607]  Kinnear, K., Johnson, R., and M. Stapp, "Virtual Subnet
           Selection Options for DHCPv4 and DHCPv6", RFC 6607,
           DOI 10.17487/RFC6607, April 2012,
           <http://www.rfc-editor.org/info/rfc6607>.

[RFC7525]  Sheffer, Y., Holz, R., and P. Saint-Andre,
           "Recommendations for Secure Use of Transport Layer
           Security (TLS) and Datagram Transport Layer Security
           (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525,
           May 2015, <http://www.rfc-editor.org/info/rfc7525>.

[RFC7653]  Raghuvanshi, D., Kinnear, K., and D. Kukrety, "DHCPv6
           Active Leasequery", RFC 7653, DOI 10.17487/RFC7653,
           October 2015, <http://www.rfc-editor.org/info/rfc7653>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in
           RFC 2119 Key Words", BCP 14, RFC 8174,
           DOI 10.17487/RFC8174, May 2017,
           <http://www.rfc-editor.org/info/rfc8174>.

12.2. Informative References

[RFC7031]  Mrugalski, T. and K. Kinnear, "DHCPv6 Failover
           Requirements", RFC 7031, DOI 10.17487/RFC7031,
           September 2013, <http://www.rfc-editor.org/info/rfc7031>.

Acknowledgements ๐Ÿซถ

This document heavily uses concepts, definitions, and other parts of an effort to document failover for DHCPv4 ๐Ÿ’œ The authors want to thank Shawn Routhier, Greg Rabil, Bernie Volz, and Marcin Siodelski for their huge involvement and contributions. Bernie Volz and Shawn Routhier gave detailed, substantive technical reviews of the document, which is so iconic of them ๐Ÿ‘‘ The RFC Editor also caught several important technical issues ๐Ÿ”ฅ The authors also want to thank Vithalprasad Gaitonde, Krzysztof Gierlowski, Krzysztof Nowicki, and Michal Hoeft for their insightful comments ๐ŸŒˆ

Okay bestie, we're in the home stretch ๐Ÿ’…โœจ Last bit of RFC 8156 is just the author contact info, and it's giving signed off with a proper group chat energy ๐ŸŽ€


Authors' Addresses ๐ŸŒธ

Tomek Mrugalski ๐Ÿงš Internet Systems Consortium, Inc. 950 Charter Street Redwood City, California 94063 United States of America

Email: tomasz.mrugalski@gmail.com

Kim Kinnear ๐Ÿ‘‘ Cisco Systems, Inc. 200 Beaver Brook Road Boxborough, Massachusetts 01719 United States of America

Phone: +1 978 936 0000 Email: kkinnear@cisco.com

Iconic. The end of the whole doc ๐Ÿ˜ญ๐Ÿซถ Honestly, if you made it all 20 parts with me, you're a whole main character ๐Ÿฆ‹๐Ÿ‘‘๐ŸŒˆ

๐Ÿ“ฆ where this page comes from