RFC 8156
DHCPv6 Failover Protocol
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 Notice ๐
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-INTERRUPTEDstate toPARTNER-DOWNstate 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
FREEstate, and available on the secondary server when it's in theFREE-BACKUPstate. 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_SERVERIDoption 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
RENEWrequests 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
BNDUPDmessage. - acknowledged partner lifetime: The partner lifetime the partner server has most recently acknowledged in a
BNDREPLYmessage.
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-typetells you which DHCP message type this is. The available types are listed below ๐transaction-idis the transaction-id for this message exchange ๐sent-timeis 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 โฐoptionsare 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-codeis OPTION_F_BINDING_STATUS (114)option-lenis 1binding-statusis 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-codeis OPTION_F_CONNECT_FLAGS (115)option-lenis 2flagsholds 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_VERSIONcontaining the protocol version that the primary server will use when sending failover messages ๐ขOPTION_F_MCLTcontaining the configured MCLT ๐OPTION_F_KEEPALIVE_TIMEcontaining 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_BNDUPDcontaining 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_NAMEcontaining 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_FLAGScontaining 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
ExcessiveTimeSkewin theOPTION_STATUS_CODEto 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 returnsNotSupportedin theOPTION_STATUS_CODEto 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 MCLTOPTION_F_KEEPALIVE_TIME: remember the keepalive-time as theFO_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 theOPTION_F_MAX_UNACKED_BNDUPDoption ๐ธ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 theOPTION_F_MCLToption 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 theFO_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 theOPTION_F_MAX_UNACKED_BNDUPDoption ๐ธ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 intoPARTNER-DOWNstate, if this server is inPARTNER-DOWNstate. if this server ISN'T inPARTNER-DOWNstate, 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 NOTPARTNER-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 theOPTION_F_SERVER_STATEisPARTNER-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_CLIENTIDcontaining the DUID of the client most recently associated with this lease MUST appear.OPTION_LQ_BASE_TIMEcontaining 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_DATAcontaining the time and reconfigure key, if any.OPTION_LQ_RELAY_DATAcontaining information described in Section 4.1.2.4 of [RFC5007], if any exists.OPTION_IA_NAorOPTION_IA_TAfor an IPv6 address, orOPTION_IA_PDfor 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 anOPTION_IA_NA,OPTION_IA_TA, orOPTION_IA_PDmust 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, andOPTION_IA_PDare 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_IAADDRfor an IPv6 address or anOPTION_IAPREFIXfor 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_STATUScontaining the binding-status MUST appear.OPTION_F_START_TIME_OF_STATEcontaining the start-time-of-state MUST appear.OPTION_F_STATE_EXPIRATION_TIME(absolute) containing thestate-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 thepartner-lifetime*.OPTION_F_PARTNER_RAW_CLT_TIME(absolute) containing the partner-raw-clt-time.OPTION_F_EXPIRATION_TIME(absolute) containing theexpiration-time*.OPTION_CLIENT_FQDNcontaining the FQDN information associated with this lease and client, if any.
- 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
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_IAPREFIXfor 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 thisOPTION_IAPREFIXoption is associated with the global, default VPN. This option MUST appear if the information in thisOPTION_IAPREFIXoption is associated with a VPN other than the global, default VPN. Support of [RFC6607] is not required, and if it is not supported, then anOPTION_VSSMUST NOT appear. If [RFC6607] is supported, then anOPTION_VSSMUST appear if and only if a VPN other than the global, default VPN is used.OPTION_LQ_BASE_TIMEcontaining the absolute time that this information was placed in thisOPTIONS_IAPREFIXoption (see Section 6.3.1 of [RFC7653]) MUST appear.OPTION_F_BINDING_STATUScontaining the binding-status MUST appear.OPTION_F_START_TIME_OF_STATEcontaining the start-time-of-state MUST appear.OPTION_F_STATE_EXPIRATION_TIME(absolute) containing thestate-expiration-time*.OPTION_F_PARTNER_LIFETIME(absolute) containing thepartner-lifetime*.OPTION_F_EXPIRATION_TIME(absolute) containing theexpiration-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:
- The OPTION_CLIENTID is used to find the client.
- The other data in the top level of the OPTION_CLIENT_DATA option is stored with the client as appropriate.
- 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:
- The IPv6 prefix is used to find the prefix.
- 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 ๐
- Entire BNDUPD: The
OPTION_STATUS_CODEwith an error is present in the outermost option of theBNDREPLY, which is either the singleOPTION_CLIENT_DATAoption or the singleOPTION_IAPREFIXoption. An example of this sort of error might be that anOPTION_VSSoption was present and specified a VPN that might not exist on the receiving server ๐ - Single address or prefix: The
OPTION_STATUS_CODEwith an error is present in a singleIAADDRorIAPREFIXoption that's itself contained in anOPTION_IA_NA,OPTION_IA_TA, orOPTION_IA_PDoption. An example of this might be that a particular IPv6 address was specified in anIAADDRoption 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_CLIENTIDcontaining the DUID of the client most recently associated with this IPv6 address.OPTION_VSSfrom theBNDUPDmessage, if any.OPTION_IA_NAorOPTION_IA_TAfor an IPv6 address, orOPTION_IA_PDfor 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_IAADDRfor an IPv6 address or anOPTION_IAPREFIXfor an IPv6 prefix.- IPv6 address or IPv6 prefix (with length).
- Inside of the IAaddr-options or IAprefix-options:
OPTION_STATUS_CODEcontaining an error code, or containing a success code if a message is required. AnOPTION_STATUS_CODEoption SHOULD NOT appear with a success code unless a message tied to that success code needs to be included. NoOPTION_STATUS_CODEoption at all means success ๐ซถOPTION_F_BINDING_STATUScontaining the binding-status received in theBNDUPDmessage.OPTION_F_STATE_EXPIRATION_TIME(absolute) containing the state-expiration-time received in theBNDUPDmessage.OPTION_F_PARTNER_LIFETIME_SENT(absolute) containing a duplicate of theOPTION_F_PARTNER_LIFETIMEreceived in theBNDUPDmessage.
- Inside of the IA_NA-options, IA_TA-options, or IA_PD-options sections:
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_VSSfrom theBNDUPDmessage, if any.OPTION_STATUS_CODEcontaining an error code, or containing a success code if a message is required. If the info in the matchingOPTION_IAPREFIXin theBNDUPDmessage was accepted and no status message was required (the usual case!), noOPTION_STATUS_CODEoption appears โจOPTION_F_BINDING_STATUScontaining the binding-status received in theBNDREPLYmessage.OPTION_F_STATE_EXPIRATION_TIME(absolute) containing the state-expiration-time received in theBNDREPLYmessage.OPTION_F_PARTNER_LIFETIME_SENT(absolute) containing a duplicate of theOPTION_F_PARTNER_LIFETIMEreceived in theBNDREPLYmessage.
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:
- The
OPTION_CLIENTIDis used to find the client. - For each of the
OPTION_IA_NA,OPTION_IA_TA, orOPTION_IA_PDoptions in theOPTION_CLIENT_DATAoption, and for each of theOPTION_IAADDRorOPTION_IAPREFIXoptions they contain:- a.
OPTION_F_PARTNER_LIFETIME_SENTis 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 ๐ฆ
- a.
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 ๐
OPTION_F_BINDING_STATUScontaining the binding-status received in theBNDREPLYmessage.OPTION_F_STATE_EXPIRATION_TIME(absolute) containing the state-expiration-time received in theBNDREPLYmessage.OPTION_F_PARTNER_LIFETIME_SENT(absolute) containing a duplicate of theOPTION_F_PARTNER_LIFETIMEreceived in theBNDREPLYmessage.
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:
NORMALorCOMMUNICATIONS-INTERRUPTED: Transition intoNORMALstate.RECOVER: Stay inCOMMUNICATIONS-INTERRUPTEDstate.RECOVER-DONE: Transition intoNORMALstate.PARTNER-DOWN,POTENTIAL-CONFLICT,CONFLICT-DONE, orRESOLUTION-INTERRUPTED: Transition intoPOTENTIAL-CONFLICTstate.
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:
- 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.
- 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 ๐ซถ
- Avoid redundant or overlapping DNS updates where both failover servers are trying to do DNS updates for the same lease-client binding ๐ โโ๏ธ
- 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:
- 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 ๐ง
- 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) โจ
- The status of any DNS update operations that are in progress or done ๐ฅ
- 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 ๐
- 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 ๐ง
- 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
- ietf: rfc8156 2017-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms