Skip to main content

A YANG Data Model for Resilient Next-Hop Groups
draft-xu-rtgwg-resilient-nexthop-group-yang-01

Document Type Active Internet-Draft (individual)
Authors Bohua Xu , Chang Liu , Yu Zhou , Chenyang Wen , Wei Cheng , Junjie Wang , Mingyu Wu , Yongtao Yang
Last updated 2026-10-27
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-xu-rtgwg-resilient-nexthop-group-yang-01
Individual Submission                                              B. Xu
Internet-Draft                                                    C. Liu
Intended status: Standards Track                                 Y. Zhou
Expires: 3 May 2027                                               C. Wen
                                                            China Unicom
                                                                W. Cheng
                                                                 J. Wang
                                                                   M. Wu
                                                                 Y. Yang
                                                                  Centec
                                                         30 October 2026

            A YANG Data Model for Resilient Next-Hop Groups
             draft-xu-rtgwg-resilient-nexthop-group-yang-01

Abstract

   This document defines a YANG data model for configuring and observing
   resilient next-hop groups.  A fixed bucket table separates flow
   hashing from member selection.  The model augments the routing
   management model with shared groups, static route bindings, weighted
   bucket targets, restoration policies, and forwarding-confirmed
   operational state.

   The specification defines distinct quota and reference restoration
   policies, consistent timer semantics, and an administrative rebalance
   action protected by a state-generation precondition.  It standardizes
   management behavior for this class of implementation; it does not
   define a new routing protocol, hash algorithm, or transport ordering
   guarantee.

Discussion and Implementation Status

   This note is to be removed before publishing as an RFC.

   This is an individual proposal intended for the Standards Track.  No
   working group adoption or independent interoperability implementation
   is claimed.  The authors invite review of the problem statement,
   overlap with existing work, and implementation experience.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

Xu, et al.                 Expires 3 May 2027                   [Page 1]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 3 May 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
     1.1.  Existing Models and Scope of the Proposal . . . . . . . .   3
   2.  Requirements Language . . . . . . . . . . . . . . . . . . . .   4
   3.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   4
   4.  Forwarding and Restoration Behavior . . . . . . . . . . . . .   5
     4.1.  Mapping and Configuration Boundary  . . . . . . . . . . .   5
     4.2.  Failure Repair and Loss of Forwarding . . . . . . . . . .   5
     4.3.  Quota Policy  . . . . . . . . . . . . . . . . . . . . . .   6
     4.4.  Reference Policy  . . . . . . . . . . . . . . . . . . . .   7
     4.5.  Recovery, Eligibility, and Timer Semantics  . . . . . . .   7
   5.  State Publication and Concurrency . . . . . . . . . . . . . .  10
     5.1.  Administrative Rebalance  . . . . . . . . . . . . . . . .  10
     5.2.  Observability and Notifications . . . . . . . . . . . . .  11
   6.  YANG Model and Route Binding  . . . . . . . . . . . . . . . .  12
   7.  YANG Module . . . . . . . . . . . . . . . . . . . . . . . . .  14
   8.  Worked Examples and Interoperability Checks . . . . . . . . .  32
     8.1.  Integer Targets . . . . . . . . . . . . . . . . . . . . .  32
     8.2.  Restoration to a Reference Assignment . . . . . . . . . .  33
     8.3.  Waiting and Stale Actions . . . . . . . . . . . . . . . .  33
     8.4.  Example IPv4 Static Route Configuration . . . . . . . . .  33

Xu, et al.                 Expires 3 May 2027                   [Page 2]
Internet-Draft          Resilient Next-Hop Groups           October 2026

     8.5.  Implementation Review Checklist . . . . . . . . . . . . .  35
   9.  Operational Considerations  . . . . . . . . . . . . . . . . .  35
   10. Security Considerations . . . . . . . . . . . . . . . . . . .  35
   11. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  36
     11.1.  XML Namespace  . . . . . . . . . . . . . . . . . . . . .  36
     11.2.  YANG Module  . . . . . . . . . . . . . . . . . . . . . .  36
   12. Normative References  . . . . . . . . . . . . . . . . . . . .  36
   13. Informative References  . . . . . . . . . . . . . . . . . . .  38
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  39

1.  Introduction

   Changing a multipath group can change the next hop selected for an
   existing flow.  The extent depends on the selection algorithm
   [RFC2992].  A bucket indirection table permits an implementation to
   repair buckets associated with a failed member while retaining other
   assignments.  Linux resilient groups provide one public
   implementation of this approach [LINUX].

   A controller managing this class of forwarding needs to distinguish
   capabilities from configured policy, decide whether an active bucket
   may move on recovery, and determine whether a reported table has
   reached the forwarding plane.  A group name and weighted member list
   do not fully express these decisions.

   This document proposes a common YANG interface for those decisions
   and observable invariants.  A controller can select a policy, read
   current assignments and their generation, then issue a guarded
   rebalance.  It does not select a particular internal hash, memory
   layout, or failure detector.  The requirements apply only to
   implementations claiming support for this module.

1.1.  Existing Models and Scope of the Proposal

   The routing model [RFC8349] defines routing configuration and
   operational RIB state.  This module augments its next-hop choices
   rather than changing their existing meaning.  The first version is
   limited to IPv4 and IPv6 unicast static-route configuration and group
   references on operational RIB routes.  Routing-protocol signaling,
   recursive group composition, encapsulation policy, and cross-router
   synchronized hashing are outside scope.

   OpenConfig already models static next-hop groups [OC-STATIC] and
   abstract forwarding state [OC-AFT]. gRIBI distinguishes RIB and FIB
   programming acknowledgments [GRIBI].  SAI provides indexed fine-
   grained ECMP groups [SAI-NHG].  Consequently, neither a shared group,
   bucket indirection, nor a forwarding acknowledgment is claimed here
   as a new mechanism.

Xu, et al.                 Expires 3 May 2027                   [Page 3]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   The proposed addition is a coherent policy and observation contract
   for bucket restoration within the IETF NMDA routing model.  The
   combination of per-group restoration selection, invariant timer
   semantics, and a generation-guarded operation requires review against
   existing interfaces.  An extension to an established model may be
   preferable if it meets the same operator need; this individual
   proposal does not establish working group demand.

   Weighted HRW [I-D.ietf-bess-weighted-hrw] addresses an algorithmic
   selection approach.  This module does not require HRW or replace it.
   Implementations with no persistent bucket table should not claim
   conformance by fabricating bucket observations.

2.  Requirements Language

   The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD 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.  Terminology

   A member has a stable group-scoped identifier, positive weight, and
   an interface and/or next-hop address.  Usability is the local
   forwarding subsystem assessment that the member can carry traffic.
   The assessment can depend on interface state, neighbor resolution, or
   liveness detection; it is not prescribed by this model.

   B is the configured number of logical buckets.  A(b) is the confirmed
   effective usable owner of bucket b; it is absent when forwarding
   through that bucket is confirmed suppressed or unassigned.  R(b) is a
   reference owner used only by the reference policy.  Raw hardware
   programming that is known to be unusable is not a usable assignment.

   A migration changes a confirmed owner to another confirmed owner.
   Initial assignment and removal are separately observable mapping
   changes and are not owner-to-owner migration counts.  A bucket is
   idle when no packet has been observed for it over the configured
   monotonic interval.  An idle bucket can still represent a live but
   temporarily silent connection.

   The quota policy seeks integer weighted shares of all B buckets over
   usable members.  The reference policy seeks a stable reference
   ownership for every currently usable reference member.  These are
   distinct balance conditions; neither promises equal traffic rates
   because bucket traffic can be uneven.

Xu, et al.                 Expires 3 May 2027                   [Page 4]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   Flow-invariant fields -> fixed hash parameters -> bucket b -> A(b)
                                                            |
   Member usability -> safety repair ------------------------+
   Per-group policy -> quota targets T or reference R -------+
   Recovery timers -> eligible discretionary movements ------+
   Controller action -> generation check -> confirmed moves -+

4.  Forwarding and Restoration Behavior

4.1.  Mapping and Configuration Boundary

   The mapping from packet fields to bucket index MUST remain
   independent of member count, member usability, and member weights.
   Changes to B or hash parameters are explicit administrative changes
   and MAY remap all flows.  Implementations MUST document their hash
   inputs and supported bucket sizes.  This model does not configure
   hash inputs or a hash seed.

   A server MUST reject unsupported bucket counts or address-family
   combinations before accepting configuration.  It MUST NOT silently
   substitute a different B.  Weights express relative bucket allocation
   rather than guaranteed bandwidth.  A member can receive zero buckets
   when B is small relative to the number or weight distribution of
   members; this does not make that member unusable.

   Configuration commits MUST be serialized with group control
   operations.  Configuration values in the operational datastore
   describe the applied configuration under NMDA [RFC8342].  If intended
   configuration cannot be applied, the server MUST retain and expose
   the actual applied state and report the error; an accepted edit is
   not a forwarding acknowledgment.  Changes of B, members, weights, or
   policy MAY migrate usable buckets and are outside the failure-only
   minimal-change rule.

4.2.  Failure Repair and Loss of Forwarding

   When a member becomes unusable, safety repair MUST take priority over
   discretionary restoration.  The repair pass MUST target buckets whose
   effective owner became unusable; it MUST NOT move a bucket with a
   still-usable owner merely to improve balance.  It MUST proceed
   without waiting for hold-down, idle-timer, or unbalanced-timer.  This
   is a scheduling requirement, not a zero-time hardware repair
   guarantee.

   Each affected bucket MUST be assigned to a currently usable member,
   or have forwarding through the failed owner suppressed when no usable
   assignment can be installed.  Before programming each new assignment
   the implementation MUST recheck destination usability.  An unusable

Xu, et al.                 Expires 3 May 2027                   [Page 5]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   member MUST NOT remain eligible for packet selection.  If the
   platform cannot suppress a failed member or confirm the result, it
   MUST report failed programming and MUST NOT claim successful repair.

   In quota policy, receivers SHOULD be selected to reduce current
   deficits against T where possible; the repair pass need not achieve T
   because that could require moving unaffected buckets.  In reference
   policy, an affected bucket MUST use its reference owner when that
   owner is usable; otherwise any usable temporary owner MAY be
   selected.  Safety repair can use a member whose recovery hold-down
   has not expired.

   If no member is usable, forwarding through the group MUST be
   suppressed.  When members become usable from that condition, all
   unassigned buckets MUST be assigned without recovery hold-down.  In
   reference policy a usable reference owner takes precedence; remaining
   buckets can use another usable owner.  Programming can be partial:
   oper-status is up only if all buckets have usable confirmed
   assignments, degraded if some do, and down if none do.

4.3.  Quota Policy

   restoration/policy=quota is the default.  With usable set U nonempty,
   let W be the sum of usable weights.  The server MUST select a fixed
   integer T_i for each member, zero for unusable members, with T_i in
   {floor(B*w_i/W), ceil(B*w_i/W)} for usable members and sum(T_i)=B.
   It MUST expose target-buckets and retain these targets until B,
   membership, weights, or usability changes.  Calculations MUST avoid
   intermediate integer overflow.

   Largest-remainder apportionment with ties resolved by ascending
   member ID is one conforming algorithm.  Identical target choices
   across devices are not required; the selected targets are observable.
   After safety repair has assigned all B buckets, every discretionary
   quota migration MUST move one bucket from a member with active-
   buckets>T_i to a usable eligible receiver with active-buckets<T_i.

   This rule removes a common rounding deadlock: if an integer deficit
   exists, an integer surplus must also exist.  Each successful quota
   migration reduces the sum of absolute deficits by two.  It does not
   ensure prompt convergence when receiver hold-down, activity, non-
   revertive mode, or programming errors prevent movements.  With U
   empty all target-buckets values MUST be zero.

Xu, et al.                 Expires 3 May 2027                   [Page 6]
Internet-Draft          Resilient Next-Hop Groups           October 2026

4.4.  Reference Policy

   A server advertising reference-restoration supports restoration/
   policy=reference; advertising the feature MUST NOT switch a group
   from quota policy.  On selecting reference policy, the server MUST
   establish R across all configured members, independently of current
   usability.  Its per-member counts MUST be floor or ceiling of the
   configured weighted share and total B.

   R MUST remain unchanged across usability transitions.  Configuration
   changes affecting B, membership, weights, or policy MAY establish a
   new R; unchanged assignments SHOULD be retained where the new
   constraints allow.  The reference-generation MUST advance whenever R
   is created or changed.  No cross-device equality of R is required.

   For discretionary reference restoration, a bucket is eligible to move
   only to its usable reference owner and only if A(b) differs from
   R(b).  Quota donor and receiver limits MUST NOT constrain this move.
   Mixing these policies can prevent restoration when a temporary owner
   is not above its instantaneous weighted share.

   With all members usable, stable R, and every required move eventually
   permitted and confirmed, A converges to R independently of the order
   of prior failures.  This is a conditional convergence property: non-
   revertive mode, disabled force timers, continuously busy buckets, or
   hardware errors can leave convergence pending indefinitely.  While a
   member is down, reference policy does not guarantee proportional
   allocation among surviving members.

4.5.  Recovery, Eligibility, and Timer Semantics

   In revertive mode a recovering member becomes eligible for
   discretionary receipt after hold-down seconds of continuous
   usability.  A fresh failure cancels its hold-down.  A continuously
   usable member remains eligible.  An initial applied configuration is
   allowed to assign traffic directly; hold-down is a recovery
   safeguard, not a deployment delay.

   For each eligible receiver with unmet policy work, the server starts
   a monotonic rebalance episode.  The episode is cleared when that
   receiver has no unmet work or loses eligibility.  Changes to B,
   weights, membership, usability, or restoration policy restart
   episodes against the new target set.  A member that becomes eligible
   later starts its own episode then. rebalance-start is only a wall-
   clock display of the episode start.

Xu, et al.                 Expires 3 May 2027                   [Page 7]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   The idle-timer describes a bucket observation interval.  The
   unbalanced-timer describes how long an eligible receiver waits before
   forced movement to it is permitted.  Zero unbalanced-timer MUST
   always mean that timer-forced movement is disabled, irrespective of
   activity support.  The expiry of a timer does not guarantee
   completion within a deadline; hardware programming can fail or be
   delayed.

   In non-revertive mode recovery MUST NOT automatically migrate
   buckets, even if they are idle or a force interval would expire.
   Safety repair, explicit configuration changes, and an accepted
   rebalance action remain permitted.  Targets and pending work MUST
   still be observable.

Xu, et al.                 Expires 3 May 2027                   [Page 8]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   +============+=============+==================+=====================+
   | Activity   | idle-timer  | unbalanced-timer | Movement            |
   | capability |             |                  | allowed after       |
   |            |             |                  | receiver            |
   |            |             |                  | eligibility         |
   +============+=============+==================+=====================+
   | Present    | >0          | 0                | Only buckets        |
   |            |             |                  | with measured       |
   |            |             |                  | idle duration       |
   |            |             |                  | >= idle-timer       |
   +------------+-------------+------------------+---------------------+
   | Present    | >0          | >0               | Idle buckets        |
   |            |             |                  | first; active       |
   |            |             |                  | buckets after       |
   |            |             |                  | receiver            |
   |            |             |                  | episode expires     |
   +------------+-------------+------------------+---------------------+
   | Present    | 0           | Any              | All donor           |
   |            |             |                  | buckets are         |
   |            |             |                  | treated as idle     |
   |            |             |                  | immediately         |
   +------------+-------------+------------------+---------------------+
   | Absent     | Unavailable | 0                | No automatic        |
   |            |             |                  | discretionary       |
   |            |             |                  | movement; wait      |
   |            |             |                  | for action or       |
   |            |             |                  | configuration       |
   +------------+-------------+------------------+---------------------+
   | Absent     | Unavailable | >0               | Force eligible      |
   |            |             |                  | movement after      |
   |            |             |                  | receiver            |
   |            |             |                  | episode expires     |
   +------------+-------------+------------------+---------------------+

        Table 1: Discretionary Automatic Movement in Revertive Mode

   Liveness safety is outside this table.  Absence of activity
   information MUST NOT be treated as evidence of idleness.  An
   implementation SHOULD show pending work to the operator when the
   configured timer policy permits indefinite waiting.  Timer behavior
   is consistent with the Linux meaning of a disabled force timer
   [LINUX], while the additional reference policy is a separate proposed
   capability.

Xu, et al.                 Expires 3 May 2027                   [Page 9]
Internet-Draft          Resilient Next-Hop Groups           October 2026

5.  State Publication and Concurrency

   boot-id is a UUID for a group incarnation.  It MUST change on group
   deletion and recreation, loss of generation state, or any generation
   reset.  Numeric generations MUST NOT wrap within an incarnation.  It
   need not change for an unrelated device process restart if the group
   state is fully preserved.

   state-generation MUST increase with each coherent publication that
   changes applied configuration, member usability or eligibility,
   targets, R, confirmed A, rebalance episode identity, or programming
   state. applied-generation MUST increase for a forwarding-confirmed
   change to effective A, including confirmed suppression or removal.
   reference-generation changes only when R is created or changed.
   Counter values and elapsed activity ages do not participate in state-
   generation.

   The server MUST publish each revision as an internally consistent
   control-state view.  While programming is outstanding it MUST show
   pending; after a failure it MUST show failed and last-programming-
   error.  A still-usable confirmed owner MAY be retained when a
   replacement fails.  The server MUST NOT expose an unconfirmed owner
   as active or increment applied-generation merely because a command
   was accepted.

   A client collecting a group in several reads MUST bracket them with
   boot-id and state-generation reads.  If either changes, the assembled
   control-state view MUST be discarded and retried.  This mechanism
   covers the defined control state only; activity ages, statistics, and
   packet observations do not become a simultaneous snapshot.  A server
   that cannot offer consistent revisions cannot claim this behavior by
   exposing an arbitrary counter.

5.1.  Administrative Rebalance

   The rebalance action requires boot-id and expected-state-generation.
   Under the same serialization used for group updates, the server MUST
   compare both before moving any bucket.  A mismatch MUST return a
   protocol operation error with error-app-tag stale-generation and
   perform no action movement.  A pending or failed programming state
   MUST reject a new action with error-app-tag group-not-ready until the
   server has reconciled its forwarding state.

Xu, et al.                 Expires 3 May 2027                  [Page 10]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   An accepted action bypasses hold-down, idle-timer, and unbalanced-
   timer.  It MUST obey the selected policy, current destination
   usability, and an optional receiving-member filter.  It performs a
   bounded pass over the current B buckets; it MUST NOT wait
   indefinitely for an unusable target to recover.  An explicitly
   selected unusable receiver MUST be rejected with error-app-tag
   member-unusable before any move.

   A liveness event MUST interrupt further discretionary action
   movements so safety repair can run.  The action returns interrupted
   with the number of its already confirmed migrations.  A programming
   failure returns failed and updates operational diagnostics.
   Otherwise complete means no work for the requested scope remains
   against the accepted stable state; it does not mean the whole group
   is balanced if a member filter was used.

   The output state-generation identifies the view at action completion.
   A later asynchronous event can change it before the client reads
   again.  Clients MUST re-read before retrying a stale or interrupted
   action.  Confirmed changes are not rolled back merely because an
   action is interrupted.  The migrated-buckets count excludes
   independent safety repair and counts no planned or unconfirmed moves.

5.2.  Observability and Notifications

   The server MUST expose the required control-state leaves in the
   module, including per-member usable, eligible, pending work, and
   active counts. target-buckets is present only in quota policy.
   Reference counts and assignments are present only in reference
   policy.  A server advertising bucket-table MUST return B bucket
   entries; an entry has no active-member when no effective usable
   assignment is confirmed.

   The model exposes cumulative failure and migration counters with a
   discontinuity timestamp.  Each confirmed migration MUST be counted
   once in the appropriate failure, idle, or forced category; a manual
   rebalance is forced even if its selected bucket happens to be idle.
   Initial assignment, removal, and configuration-driven replacement are
   not included in those three migration categories.  A counter
   discontinuity MUST update discontinuity-time.

Xu, et al.                 Expires 3 May 2027                  [Page 11]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   resilient-group-event includes group, event category, boot-id, state-
   generation, and the count of confirmed migrations for that event.  A
   failure event can report zero migrations while repair is pending.
   Notifications MAY be coalesced or rate-limited and MUST NOT be
   treated as a lossless transaction log.  Reading the current state is
   the recovery procedure.  Time correlation with buffer telemetry is an
   operational analysis; it neither proves causality nor creates a
   dependency between the two protocols.

6.  YANG Model and Route Binding

   The module uses YANG 1.1 [RFC7950] and NMDA [RFC8342], importing the
   common types [RFC9911], interfaces [RFC8343], and routing modules
   [RFC8349].  The three independent features are bucket-activity,
   bucket-table, and reference-restoration.  They advertise server
   capabilities; restoration/policy and restoration/mode select behavior
   per group.

   Static IPv4 and IPv6 routes gain a next-hop choice that references a
   configured group.  The reference MUST resolve and its address family
   MUST match the route.  Deleting a referenced group is invalid unless
   the referencing routes are changed in the same valid configuration.
   Operational RIB references do not require the configuration to remain
   present indefinitely.

   An IPv6 link-local next-hop address requires an outgoing interface.
   The model uses case-independent prefix checking and no-zone address
   types; a zone suffix is not an alternative to an explicit interface
   reference.  Other next hops may identify an interface, an address, or
   both.  Recursive resolution is a local implementation matter and MUST
   not create a forwarding loop or violate the usability rules.

   The following tree is generated from the accompanying module and uses
   [RFC8340] notation.  The module organization and contact identify an
   individual proposal rather than asserting working group ownership.
   RFC XXXX is an RFC Editor placeholder to be replaced upon
   publication.

   module: ietf-resilient-next-hop-group

     augment /rt:routing:
       +--rw resilient-next-hop-groups
          +--rw group* [name]
             +---x rebalance
             |  +---w input
             |  |  +---w boot-id                      yang:uuid
             |  |  +---w expected-state-generation    uint64
             |  |  +---w member?

Xu, et al.                 Expires 3 May 2027                  [Page 12]
Internet-Draft          Resilient Next-Hop Groups           October 2026

             |  |          -> ../../member/id
             |  +--ro output
             |     +--ro result              enumeration
             |     +--ro migrated-buckets    uint32
             |     +--ro state-generation    uint64
             +--rw name                      string
             +--rw description?              string
             +--rw address-family            identityref
             +--rw bucket-count?             uint32
             +--rw idle-timer?               uint32 {bucket-activity}?
             +--rw unbalanced-timer?         uint32
             +--rw restoration
             |  +--rw mode?        identityref
             |  +--rw hold-down?   uint32
             |  +--rw policy?      enumeration
             +--rw member* [id]
             |  +--rw id                       uint32
             |  +--rw outgoing-interface?      if:interface-ref
             |  +--rw next-hop-ipv4-address?
             |  |       inet:ipv4-address-no-zone
             |  +--rw next-hop-ipv6-address?
             |  |       inet:ipv6-address-no-zone
             |  +--rw weight?                  uint32
             |  +--ro usable                   boolean
             |  +--ro rebalance-pending        boolean
             |  +--ro target-buckets?          uint32
             |  +--ro active-buckets           uint32
             |  +--ro reference-buckets?       uint32
             |  |       {reference-restoration}?
             |  +--ro last-transition?         yang:date-and-time
             |  +--ro eligible                 boolean
             |  +--ro rebalance-start?         yang:date-and-time
             +--ro oper-status               enumeration
             +--ro boot-id                   yang:uuid
             +--ro applied-generation        uint64
             +--ro programming-status        enumeration
             +--ro last-programming-error?   string
             +--ro reference-restored?       boolean
             |       {reference-restoration}?
             +--ro usable-members            uint32
             +--ro balanced                  boolean
             +--ro reference-generation?     uint64
             |       {reference-restoration}?
             +--ro bucket* [index] {bucket-table}?
             |  +--ro index               uint32
             |  +--ro active-member?      -> ../../member/id
             |  +--ro reference-member?   -> ../../member/id
             |  |       {reference-restoration}?

Xu, et al.                 Expires 3 May 2027                  [Page 13]
Internet-Draft          Resilient Next-Hop Groups           October 2026

             |  +--ro idle-time?          uint32 {bucket-activity}?
             +--ro statistics
             |  +--ro discontinuity-time?    yang:date-and-time
             |  +--ro member-failures?       yang:counter64
             |  +--ro member-restorations?   yang:counter64
             |  +--ro failure-migrations?    yang:counter64
             |  +--ro idle-migrations?       yang:counter64
             |  +--ro forced-migrations?     yang:counter64
             +--ro state-generation          uint64
     augment /rt:routing/rt:control-plane-protocols
               /rt:control-plane-protocol/rt:static-routes/v4ur:ipv4
               /v4ur:route/v4ur:next-hop/v4ur:next-hop-options:
       +--:(resilient-next-hop-group)
          +--rw resilient-next-hop-group    leafref
     augment /rt:routing/rt:control-plane-protocols
               /rt:control-plane-protocol/rt:static-routes/v6ur:ipv6
               /v6ur:route/v6ur:next-hop/v6ur:next-hop-options:
       +--:(resilient-next-hop-group)
          +--rw resilient-next-hop-group    leafref
     augment /rt:routing/rt:ribs/rt:rib/rt:routes/rt:route/rt:next-hop
               /rt:next-hop-options:
       +--:(resilient-next-hop-group)
          +--ro resilient-next-hop-group?   leafref

     notifications:
       +---n resilient-group-event
          +--ro group               leafref
          +--ro event               identityref
          +--ro member?             uint32
          +--ro migrated-buckets    uint32
          +--ro boot-id             yang:uuid
          +--ro state-generation    uint64

7.  YANG Module

   module "ietf-resilient-next-hop-group" {
     yang-version "1.1";
     namespace
       "urn:ietf:params:xml:ns:yang:ietf-resilient-next-hop-grou"
     + "p";
     prefix "rnhg";
     import "ietf-yang-types" {
       prefix "yang";
       reference
         "RFC 9911: Common YANG Data Types";
     }
     import "ietf-inet-types" {
       prefix "inet";

Xu, et al.                 Expires 3 May 2027                  [Page 14]
Internet-Draft          Resilient Next-Hop Groups           October 2026

       reference
         "RFC 9911: Common YANG Data Types";
     }
     import "ietf-interfaces" {
       prefix "if";
       reference
         "RFC 8343: A YANG Data Model for Interface Management";
     }
     import "ietf-routing" {
       prefix "rt";
       reference
         "RFC 8349: A YANG Data Model for Routing Management (NMDA
          Version)";
     }
     import "ietf-ipv4-unicast-routing" {
       prefix "v4ur";
       reference
         "RFC 8349: A YANG Data Model for Routing Management (NMDA
          Version)";
     }
     import "ietf-ipv6-unicast-routing" {
       prefix "v6ur";
       reference
         "RFC 8349: A YANG Data Model for Routing Management (NMDA
          Version)";
     }
     organization
       "Authors of this individual Internet-Draft";
     contact
       "Bohua Xu <xubh15@chinaunicom.cn> Junjie Wang
        <wangjj@centec.com> Discussion: <rtgwg@ietf.org> This
        module has not been adopted by a working group.";
     description
       "Configuration and operational state for resilient next-hop
        groups. This module augments the NMDA routing model with
        bucket policies, forwarding confirmation, and guarded
        administrative rebalancing.

        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 (RFC 2119) (RFC 8174)
        when, and only when, they appear in all capitals, as shown
        here.

        Copyright (c) 2026 IETF Trust and the persons identified as
        authors of the code. All rights reserved.

Xu, et al.                 Expires 3 May 2027                  [Page 15]
Internet-Draft          Resilient Next-Hop Groups           October 2026

        Redistribution and use in source and binary forms, with or
        without modification, is permitted pursuant to, and subject
        to the license terms contained in, the Revised BSD License
        set forth in Section 4.c of the IETF Trust's Legal
        Provisions Relating to IETF Documents
        (https://trustee.ietf.org/license-info).

        This version of this YANG module is part of RFC XXXX
        (https://www.rfc-editor.org/info/rfcXXXX); see the RFC
        itself for full legal notices.";
     revision "2026-10-30" {
       description
         "Initial revision.";
       reference
         "RFC XXXX: A YANG Data Model for Resilient Next-Hop Groups";
     }
     feature "bucket-activity" {
       description
         "Supports idle-based migration and per-bucket activity
          measurement. Activity support does not imply that an idle
          bucket has no live transport sessions. Independent of
          bucket-table support.";
     }
     feature "bucket-table" {
       description
         "Indicates that the server exposes the per-bucket
          operational indirection table.";
     }
     feature "reference-restoration" {
       description
         "Supports the reference value of restoration/policy and
          its operational state. Advertising the feature does not
          select that policy. It is independent of bucket-activity
          and bucket-table.";
       reference
         "RFC XXXX: A YANG Data Model for Resilient Next-Hop Groups";
     }
     identity "restoration-mode" {
       description
         "Base identity for member recovery bucket restoration
          modes.";
     }
     identity "revertive" {
       base "restoration-mode";
       description
         "Buckets are automatically eligible for migration back to
          a recovered member after the hold-down timer expires,
          governed by the idle-timer and unbalanced-timer.";

Xu, et al.                 Expires 3 May 2027                  [Page 16]
Internet-Draft          Resilient Next-Hop Groups           October 2026

       reference
         "RFC XXXX: A YANG Data Model for Resilient Next-Hop Groups";
     }
     identity "non-revertive" {
       base "restoration-mode";
       description
         "Buckets are not automatically migrated when a member
          recovers; rebalancing occurs only when explicitly invoked
          via the 'rebalance' action.";
       reference
         "RFC XXXX: A YANG Data Model for Resilient Next-Hop Groups";
     }
     identity "group-event" {
       description
         "Base identity for operational lifecycle events reported
          for a resilient next-hop group.";
     }
     identity "member-failure" {
       base "group-event";
       description
         "A member became unusable; repair may still be pending or
          failed.";
     }
     identity "member-restoration" {
       base "group-event";
       description
         "Buckets were migrated to a recovered usable member.";
     }
     identity "rebalance" {
       base "group-event";
       description
         "Buckets were migrated in response to an explicit
          'rebalance' action.";
     }
     identity "configuration-change" {
       base "group-event";
       description
         "Buckets were recomputed and migrated due to an
          administrative configuration change.";
     }
     identity "group-down" {
       base "group-event";
       description
         "All members of the resilient next-hop group became
          unusable.";
     }
     grouping "group-ref" {
       description

Xu, et al.                 Expires 3 May 2027                  [Page 17]
Internet-Draft          Resilient Next-Hop Groups           October 2026

         "Reusable reference to a configured resilient next-hop
          group.";
       leaf "resilient-next-hop-group" {
         type "leafref" {
           path
             "/rt:routing/rnhg:resilient-next-hop-groups/rnhg:gr"
           + "oup/rnhg:name";
         }
         mandatory "true";
         description
           "Name of the resilient next-hop group used as the route
            next hop.";
       }
     }
     notification "resilient-group-event" {
       description
         "Reports a published control-state change. Notification
          delivery is not a durable event log; clients read current
          state to recover. boot-id and state-generation identify
          the state publication.";
       leaf "group" {
         type "leafref" {
           path
             "/rt:routing/rnhg:resilient-next-hop-groups/rnhg:gr"
           + "oup/rnhg:name";
           require-instance "false";
         }
         mandatory "true";
         description
           "The resilient next-hop group that experienced the
            event.";
       }
       leaf "event" {
         type "identityref" {
           base "group-event";
         }
         mandatory "true";
         description
           "The category of group lifecycle or migration event.";
       }
       leaf "member" {
         type "uint32";
         description
           "The member identifier associated with the event, when
            applicable.";
       }
       leaf "migrated-buckets" {
         type "uint32";

Xu, et al.                 Expires 3 May 2027                  [Page 18]
Internet-Draft          Resilient Next-Hop Groups           October 2026

         mandatory "true";
         description
           "Confirmed owner-to-owner changes in this event, zero if
            none. An event does not assert that all planned repairs
            succeeded.";
       }
       leaf "boot-id" {
         type "yang:uuid";
         mandatory "true";
         description
           "Group incarnation for this event.";
       }
       leaf "state-generation" {
         type "uint64";
         mandatory "true";
         description
           "State publication associated with this event.";
       }
     }
     augment "/rt:routing" {
       description
         "Augments the routing subsystem with resilient next-hop
          groups.";
       container "resilient-next-hop-groups" {
         description
           "Container for resilient next-hop group configurations
            and operational state.";
         list "group" {
           key "name";
           description
             "A resilient group. Configuration nodes in operational
              represent the applied configuration. A server
              publishes state coherently under state-generation. A
              new group incarnation has a new boot-id.";
           action "rebalance" {
             description
               "Force a bounded administrative rebalance. Bypasses
                hold-down, idle and unbalanced timers, while
                preserving current usability and policy
                constraints. The precondition is checked atomically
                before any movement. Liveness changes interrupt
                remaining work. The reply counts confirmed moves
                only; the operation is not rollback-atomic.";
             input {
               leaf "boot-id" {
                 type "yang:uuid";
                 mandatory "true";
                 description

Xu, et al.                 Expires 3 May 2027                  [Page 19]
Internet-Draft          Resilient Next-Hop Groups           October 2026

                   "Expected group boot-id; mismatch returns
                    stale-generation.";
               }
               leaf "expected-state-generation" {
                 type "uint64";
                 mandatory "true";
                 description
                   "Expected state-generation, checked at action
                    acceptance under the group serialization lock.
                    Mismatch returns stale-generation.";
               }
               leaf "member" {
                 type "leafref" {
                   path "../../member/id";
                 }
                 description
                   "Optional receiving member. If absent, process
                    all usable receivers.";
               }
             }
             output {
               leaf "result" {
                 type "enumeration" {
                   enum "complete" {
                     description
                       "No eligible work for the requested scope
                        remains.";
                   }
                   enum "interrupted" {
                     description
                       "A liveness or control-state change stopped
                        further work.";
                   }
                   enum "failed" {
                     description
                       "Forwarding programming failed; inspect
                        operational state.";
                   }
                 }
                 mandatory "true";
                 description
                   "Outcome of this accepted action.";
               }
               leaf "migrated-buckets" {
                 type "uint32";
                 mandatory "true";
                 description
                   "Number of confirmed owner-to-owner changes made

Xu, et al.                 Expires 3 May 2027                  [Page 20]
Internet-Draft          Resilient Next-Hop Groups           October 2026

                    by this action. Safety repair after an
                    interruption is excluded.";
               }
               leaf "state-generation" {
                 type "uint64";
                 mandatory "true";
                 description
                   "State-generation at completion of this action
                    reply.";
               }
             }
           }
           leaf "name" {
             type "string" {
               length "1..64";
             }
             description
               "Unique administrative name of the resilient
                next-hop group.";
           }
           leaf "description" {
             type "string";
             description
               "Human-readable description of the group.";
           }
           leaf "address-family" {
             type "identityref" {
               base "rt:address-family";
             }
             must
               "derived-from-or-self(., 'rt:ipv4') or derived-fr"
             + "om-or-self(., 'rt:ipv6')" {
               error-message
                 "Only IPv4 and IPv6 unicast groups are defined.";
             }
             mandatory "true";
             description
               "IPv4 or IPv6 unicast address family for this group.";
           }
           leaf "bucket-count" {
             type "uint32" {
               range "1..65535";
             }
             default "128";
             description
               "Number B of logical buckets. Hardware limitations
                are validated before accepting configuration; an
                unsupported size is rejected. Changing B can remap

Xu, et al.                 Expires 3 May 2027                  [Page 21]
Internet-Draft          Resilient Next-Hop Groups           October 2026

                all flows and requires a configuration commit.";
             reference
               "RFC XXXX: A YANG Data Model for Resilient Next-Hop
                Groups";
           }
           leaf "idle-timer" {
             if-feature "bucket-activity";
             type "uint32" {
               range "0..65535";
             }
             units "seconds";
             default "120";
             description
               "Seconds without observed packets before a bucket is
                idle. Zero explicitly makes all buckets eligible
                for idle-based movement. Idleness does not imply
                the absence of established sessions.";
             reference
               "RFC XXXX: A YANG Data Model for Resilient Next-Hop
                Groups";
           }
           leaf "unbalanced-timer" {
             type "uint32" {
               range "0..65535";
             }
             units "seconds";
             default "0";
             description
               "Seconds after an eligible receiver develops unmet
                work before automatic forced movement to that
                receiver is permitted. Zero always disables
                timer-forced movement, including when bucket
                activity is unavailable. Uses monotonic elapsed
                time. It is not a guarantee on hardware programming
                completion time.";
             reference
               "RFC XXXX: A YANG Data Model for Resilient Next-Hop
                Groups";
           }
           container "restoration" {
             description
               "Parameters governing bucket restoration when a
                failed member becomes usable again.";
             leaf "mode" {
               type "identityref" {
                 base "restoration-mode";
               }
               default "rnhg:revertive";

Xu, et al.                 Expires 3 May 2027                  [Page 22]
Internet-Draft          Resilient Next-Hop Groups           October 2026

               description
                 "Specifies whether bucket restoration occurs
                  automatically (revertive) or only via explicit
                  action (non-revertive).";
             }
             leaf "hold-down" {
               type "uint32" {
                 range "0..3600";
               }
               units "seconds";
               default "0";
               description
                 "Seconds of continuous usability after recovery
                  before a member can receive discretionary
                  automatic migrations. Does not delay failure
                  repair, allocation from a down group,
                  configuration application, or an explicit
                  rebalance action.";
             }
             leaf "policy" {
               type "enumeration" {
                 enum "quota" {
                   description
                     "Use integer weighted targets for usable
                      members.";
                 }
                 enum "reference" {
                   if-feature "reference-restoration";
                   description
                     "Restore the reference assignment for usable
                      owners.";
                 }
               }
               default "quota";
               description
                 "Select the per-group restoration policy.";
             }
           }
           list "member" {
             must
               "outgoing-interface or next-hop-ipv4-address or n"
             + "ext-hop-ipv6-address" {
               error-message
                 "Each member must specify an outgoing-interface"
               + ", a\nnext-hop address, or both.";
               description
                 "Ensures each member identifies a valid forwarding
                  next hop.";

Xu, et al.                 Expires 3 May 2027                  [Page 23]
Internet-Draft          Resilient Next-Hop Groups           October 2026

             }
             must
               "not(starts-with(translate(next-hop-ipv6-address,"
             + " 'ABCDEF', 'abcdef'), 'fe8') or starts-with(tran"
             + "slate(next-hop-ipv6-address, 'ABCDEF', 'abcdef')"
             + ", 'fe9') or starts-with(translate(next-hop-ipv6-"
             + "address, 'ABCDEF', 'abcdef'), 'fea') or starts-w"
             + "ith(translate(next-hop-ipv6-address, 'ABCDEF', '"
             + "abcdef'), 'feb')) or outgoing-interface" {
               error-message
                 "An IPv6 link-local next hop requires outgoing-"
               + "interface.";
               description
                 "Case-independent fe80::/10 interface-scope
                  validation.";
             }
             key "id";
             min-elements "1";
             description
               "Configured next-hop members of the resilient group.";
             leaf "id" {
               type "uint32";
               description
                 "Unique numeric identifier of the member within
                  the group.";
             }
             leaf "outgoing-interface" {
               type "if:interface-ref";
               description
                 "Outgoing interface for this next-hop member.";
             }
             leaf "next-hop-ipv4-address" {
               when
                 "derived-from-or-self(../../address-family, 'rt"
               + ":ipv4')";
               type "inet:ipv4-address-no-zone";
               description
                 "IPv4 next-hop address of the member.";
             }
             leaf "next-hop-ipv6-address" {
               when
                 "derived-from-or-self(../../address-family, 'rt"
               + ":ipv6')";
               type "inet:ipv6-address-no-zone";
               description
                 "IPv6 next-hop address of the member.";
             }
             leaf "weight" {

Xu, et al.                 Expires 3 May 2027                  [Page 24]
Internet-Draft          Resilient Next-Hop Groups           October 2026

               type "uint32" {
                 range "1..max";
               }
               default "1";
               description
                 "Relative load-sharing weight of the member (w_i).
                  Target bucket allocation is proportional to w_i.";
             }
             leaf "usable" {
               type "boolean";
               config "false";
               mandatory "true";
               description
                 "Indicates whether this member is currently
                  resolved and usable for packet forwarding.";
             }
             leaf "rebalance-pending" {
               type "boolean";
               config "false";
               mandatory "true";
               description
                 "True if the member is usable and currently holds
                  fewer buckets than its target quota (or has
                  un-restored reference buckets) awaiting
                  migration.";
             }
             leaf "target-buckets" {
               when "../../restoration/policy = 'quota'";
               type "uint32";
               config "false";
               description
                 "Current integer target bucket count (T_i) in
                  proportional quota mode; omitted when operating
                  under reference-restoration policy.";
             }
             leaf "active-buckets" {
               type "uint32";
               config "false";
               mandatory "true";
               description
                 "Count of logical buckets with a confirmed usable
                  assignment to this member. A suppressed unusable
                  hardware entry is not counted.";
             }
             leaf "reference-buckets" {
               when "../../restoration/policy = 'reference'";
               if-feature "reference-restoration";
               type "uint32";

Xu, et al.                 Expires 3 May 2027                  [Page 25]
Internet-Draft          Resilient Next-Hop Groups           October 2026

               config "false";
               description
                 "Number of buckets whose canonical baseline
                  reference assignment R(b) points to this member.";
             }
             leaf "last-transition" {
               type "yang:date-and-time";
               config "false";
               description
                 "Timestamp of the most recent change in this
                  member's 'usable' state.";
             }
             leaf "eligible" {
               type "boolean";
               config "false";
               mandatory "true";
               description
                 "True when usable and the hold-down for automatic
                  receipt has expired. Safety repair and
                  administrative action may bypass it.";
             }
             leaf "rebalance-start" {
               type "yang:date-and-time";
               config "false";
               description
                 "Wall-clock display of the start of the current
                  eligible unmet-work episode. Absent without such
                  an episode. Timers use monotonic time, not
                  subtraction of this timestamp.";
             }
           }
           leaf "oper-status" {
             type "enumeration" {
               enum "up" {
                 description
                   "Every bucket has a confirmed usable effective
                    owner.";
               }
               enum "down" {
                 description
                   "No bucket has a confirmed usable effective
                    owner.";
               }
               enum "degraded" {
                 description
                   "Some, but not all, buckets have confirmed
                    usable owners.";
               }

Xu, et al.                 Expires 3 May 2027                  [Page 26]
Internet-Draft          Resilient Next-Hop Groups           October 2026

             }
             config "false";
             mandatory "true";
             description
               "Forwarding availability of the group, derived from
                confirmed effective bucket assignments, not merely
                member liveness.";
           }
           leaf "boot-id" {
             type "yang:uuid";
             config "false";
             mandatory "true";
             description
               "UUID identifying this group incarnation and counter
                epoch. Changes on recreation or any loss/reset of
                generation state. It is not necessarily a device
                reboot identifier.";
           }
           leaf "applied-generation" {
             type "uint64";
             config "false";
             mandatory "true";
             description
               "Counter advanced on each forwarding-confirmed
                change of effective active assignments, including
                confirmed removal or suppression. State-generation
                also advances for the publication. No wrap within
                boot-id. This is not a general configuration
                revision.";
           }
           leaf "programming-status" {
             type "enumeration" {
               enum "ready" {
                 description
                   "The latest bucket table update has been
                    confirmed by the forwarding plane.";
               }
               enum "pending" {
                 description
                   "A bucket table update is in progress and not
                    yet confirmed by the forwarding plane.";
               }
               enum "failed" {
                 description
                   "The most recent forwarding-plane update failed.";
               }
             }
             config "false";

Xu, et al.                 Expires 3 May 2027                  [Page 27]
Internet-Draft          Resilient Next-Hop Groups           October 2026

             mandatory "true";
             description
               "Status of hardware/forwarding-plane programming for
                the group.";
           }
           leaf "last-programming-error" {
             type "string";
             config "false";
             description
               "Last programming error. Absent after a subsequent
                successful programming transaction has cleared the
                error.";
           }
           leaf "reference-restored" {
             when "../restoration/policy = 'reference'";
             if-feature "reference-restoration";
             type "boolean";
             config "false";
             description
               "True when at least one member is usable, all
                buckets have confirmed usable assignments, and
                every usable reference owner owns its reference
                buckets. This does not promise intermediate weight
                balance.";
           }
           leaf "usable-members" {
             type "uint32";
             config "false";
             mandatory "true";
             description
               "Current count of usable members in the group.";
           }
           leaf "balanced" {
             type "boolean";
             config "false";
             mandatory "true";
             description
               "True if all buckets are assigned to usable members
                and the active restoration policy's balance
                condition is satisfied.";
           }
           leaf "reference-generation" {
             when "../restoration/policy = 'reference'";
             if-feature "reference-restoration";
             type "uint64";
             config "false";
             description
               "Advanced whenever R is created or changed.

Xu, et al.                 Expires 3 May 2027                  [Page 28]
Internet-Draft          Resilient Next-Hop Groups           October 2026

                Usability transitions never change R. Meaningful
                only in reference policy. No wrap within boot-id.";
           }
           list "bucket" {
             if-feature "bucket-table";
             key "index";
             config "false";
             description
               "Operational state of individual hash buckets in the
                group's indirection table.";
             leaf "index" {
               type "uint32";
               must ". < ../../bucket-count" {
                 error-message
                   "Bucket index must be less than bucket-count.";
               }
               description
                 "Zero-based bucket index (0 .. bucket-count - 1).";
             }
             leaf "active-member" {
               type "leafref" {
                 path "../../member/id";
                 require-instance "false";
               }
               description
                 "Confirmed effective usable owner. Absent for a
                  confirmed suppressed or unassigned bucket.
                  Unknown hardware state is reported as failed
                  programming and must not be presented as
                  successful repair.";
             }
             leaf "reference-member" {
               when "../../restoration/policy = 'reference'";
               if-feature "reference-restoration";
               type "leafref" {
                 path "../../member/id";
                 require-instance "false";
               }
               description
                 "Canonical reference member ID for this bucket
                  (R(b)).";
             }
             leaf "idle-time" {
               if-feature "bucket-activity";
               type "uint32";
               units "seconds";
               description
                 "Monotonic seconds since a packet was observed for

Xu, et al.                 Expires 3 May 2027                  [Page 29]
Internet-Draft          Resilient Next-Hop Groups           October 2026

                  this bucket, saturated at 4294967295. Not covered
                  by state-generation; absent when activity data is
                  unavailable.";
             }
           }
           container "statistics" {
             config "false";
             description
               "Cumulative operational counters for the resilient
                next-hop group.";
             leaf "discontinuity-time" {
               type "yang:date-and-time";
               description
                 "Timestamp of the most recent occasion on which
                  one or more counters experienced a discontinuity.";
             }
             leaf "member-failures" {
               type "yang:counter64";
               description
                 "Total number of transitions of any member from
                  usable to unusable.";
             }
             leaf "member-restorations" {
               type "yang:counter64";
               description
                 "Total number of transitions of any member from
                  unusable to usable.";
             }
             leaf "failure-migrations" {
               type "yang:counter64";
               description
                 "Total number of immediate bucket migrations
                  triggered by member failures.";
             }
             leaf "idle-migrations" {
               type "yang:counter64";
               description
                 "Total number of idle-based bucket migrations
                  performed while the migrated bucket was idle.";
             }
             leaf "forced-migrations" {
               type "yang:counter64";
               description
                 "Total number of bucket migrations performed on
                  active buckets due to unbalanced-timer expiry or
                  explicit 'rebalance' action invocation.";
             }
           }

Xu, et al.                 Expires 3 May 2027                  [Page 30]
Internet-Draft          Resilient Next-Hop Groups           October 2026

           leaf "state-generation" {
             type "uint64";
             config "false";
             mandatory "true";
             description
               "Revision of applied configuration, usability,
                eligibility, targets, reference and active
                assignments, and programming state. Increment on
                each coherent publication affecting these values.
                Excludes activity ages and statistics. Does not
                wrap within boot-id.";
           }
         }
       }
     }
     augment
       "/rt:routing/rt:control-plane-protocols/rt:control-plane-"
     + "protocol/rt:static-routes/v4ur:ipv4/v4ur:route/v4ur:next"
     + "-hop/v4ur:next-hop-options" {
       description
         "Enables an IPv4 static route to reference a resilient
          next-hop group.";
       case "resilient-next-hop-group" {
         uses "group-ref" {
           refine "resilient-next-hop-group" {
             must
               "derived-from-or-self(/rt:routing/rnhg:resilient-"
             + "next-hop-groups/rnhg:group[rnhg:name = current()"
             + "]/rnhg:address-family, 'rt:ipv4')" {
               error-message
                 "The referenced resilient next-hop group must b"
               + "e\nconfigured for the IPv4 address family.";
             }
           }
         }
       }
     }
     augment
       "/rt:routing/rt:control-plane-protocols/rt:control-plane-"
     + "protocol/rt:static-routes/v6ur:ipv6/v6ur:route/v6ur:next"
     + "-hop/v6ur:next-hop-options" {
       description
         "Enables an IPv6 static route to reference a resilient
          next-hop group.";
       case "resilient-next-hop-group" {
         uses "group-ref" {
           refine "resilient-next-hop-group" {
             must

Xu, et al.                 Expires 3 May 2027                  [Page 31]
Internet-Draft          Resilient Next-Hop Groups           October 2026

               "derived-from-or-self(/rt:routing/rnhg:resilient-"
             + "next-hop-groups/rnhg:group[rnhg:name = current()"
             + "]/rnhg:address-family, 'rt:ipv6')" {
               error-message
                 "The referenced resilient next-hop group must b"
               + "e\nconfigured for the IPv6 address family.";
             }
           }
         }
       }
     }
     augment
       "/rt:routing/rt:ribs/rt:rib/rt:routes/rt:route/rt:next-ho"
     + "p/rt:next-hop-options" {
       description
         "Exposes the resilient next-hop group bound to an active
          route in the Routing Information Base (RIB).";
       case "resilient-next-hop-group" {
         leaf "resilient-next-hop-group" {
           type "leafref" {
             path
               "/rt:routing/rnhg:resilient-next-hop-groups/rnhg:"
             + "group/rnhg:name";
             require-instance "false";
           }
           description
             "Name of the resilient next-hop group used by this
              active RIB route.";
         }
       }
     }
   }

8.  Worked Examples and Interoperability Checks

8.1.  Integer Targets

   For B=5 and two usable equal-weight members, valid targets are (3,2)
   or (2,3).  If A has counts (4,1) and the selected targets are (3,2),
   one permitted donor-to-receiver migration reaches the target.
   Testing against real shares (2.5,2.5) instead of fixed integer
   targets can incorrectly keep the group pending or cause oscillation.
   The wire model exposes the selected integer values.

Xu, et al.                 Expires 3 May 2027                  [Page 32]
Internet-Draft          Resilient Next-Hop Groups           October 2026

8.2.  Restoration to a Reference Assignment

   +===================================+===============+===============+
   | Step                              | Reference R   | Active A      |
   +===================================+===============+===============+
   | Initial                           | [1,2,3,1,2,3] | [1,2,3,1,2,3] |
   +-----------------------------------+---------------+---------------+
   | 1 fails                           | Unchanged     | [2,2,3,2,2,3] |
   +-----------------------------------+---------------+---------------+
   | 2 fails                           | Unchanged     | [3,3,3,3,3,3] |
   +-----------------------------------+---------------+---------------+
   | 1 recovers and its                | Unchanged     | [1,3,3,1,3,3] |
   | work completes                    |               |               |
   +-----------------------------------+---------------+---------------+
   | 2 recovers and its                | Unchanged     | [1,2,3,1,2,3] |
   | work completes                    |               |               |
   +-----------------------------------+---------------+---------------+

              Table 2: Reference Restoration with Two Failures

   Temporary holders in this example are choices, not a prescribed
   allocation algorithm.  Reversing recovery order also reaches R when
   the same conditional convergence requirements hold.  Recovery of a
   reference owner moves only its reference buckets; it does not impose
   quota balance on the temporary holders.

8.3.  Waiting and Stale Actions

   With no bucket-activity capability and unbalanced-timer=0, a
   recovered member can remain pending in revertive mode.  This is
   intentional: the server has neither evidence of idleness nor
   permission for timer-forced movement.  Setting a positive force timer
   or invoking a guarded action can progress the work.

   If a client reads state-generation=8 and a member becomes unusable
   without any mapping update yet confirmed, state-generation still
   advances for the liveness change.  An action carrying 8 is rejected.
   Comparing only applied-generation would miss this change, which is
   why the action precondition uses state-generation.

8.4.  Example IPv4 Static Route Configuration

   This JSON configuration is validated against the module and its
   dependencies.  It uses the default quota policy.  The address and
   interface values are illustrative.

Xu, et al.                 Expires 3 May 2027                  [Page 33]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   {
    "ietf-interfaces:interfaces": {
     "interface": [
      {
       "name": "eth0",
       "type": "iana-if-type:ethernetCsmacd"
      }
     ]
    },
    "ietf-routing:routing": {
     "ietf-resilient-next-hop-group:resilient-next-hop-groups": {
      "group": [
       {
        "name": "fabric",
        "address-family": "ietf-routing:ipv4",
        "bucket-count": 8,
        "member": [
         {
          "id": 1,
          "next-hop-ipv4-address": "192.0.2.1",
          "outgoing-interface": "eth0"
         }
        ]
       }
      ]
     },
     "control-plane-protocols": {
      "control-plane-protocol": [
       {
        "type": "ietf-routing:static",
        "name": "static",
        "static-routes": {
         "ietf-ipv4-unicast-routing:ipv4": {
          "route": [
           {
            "destination-prefix": "192.0.2.0/24",
            "next-hop": {
             "ietf-resilient-next-hop-group:resilient-next-hop-group":
     "fabric"
            }
           }
          ]
         }
        }
       }
      ]
     }
    }

Xu, et al.                 Expires 3 May 2027                  [Page 34]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   }

8.5.  Implementation Review Checklist

   Interoperability testing SHOULD exercise all eight feature
   combinations, both restoration modes, the timer combinations in
   Table 1, fractional weighted shares, B smaller than member count,
   all-members-down recovery, hardware rejection after partial
   programming, action interruption, configuration changes during
   pending work, counter discontinuity, and group recreation with the
   same name.

   Schema validation SHOULD cover address-family mismatches, unresolved
   route references, uppercase and lowercase IPv6 link-local addresses
   without an interface, invalid weights and bucket counts, and
   reference policy selection when the feature is absent.  Behavior
   simulations and schema tests do not substitute for two independent
   forwarding implementations.

9.  Operational Considerations

   Idle intervals should be chosen with expected traffic gaps and
   session affinity in mind.  No finite idle interval proves that a
   stateful service has forgotten a flow.  Non-revertive mode can avoid
   automatic recovery movements, but cannot prevent required failure
   repair or administrator-initiated changes.

   Reference policy provides repeatable placement within one reference
   generation.  It can require more movements than a policy that merely
   reaches current quotas, and can temporarily produce uneven survivor
   allocation.  Operators should select it only when restoration to the
   recorded baseline matters.

   Resilient local assignment does not guarantee transport ordering,
   losslessness, or availability of state at a replacement middlebox.  A
   changed path can have different latency; even a flow that keeps its
   local next hop can encounter changes downstream.  These limits SHOULD
   be disclosed in implementation documentation.

10.  Security Considerations

   This section follows the YANG security guidance in [RFC9907].  The
   module is intended for use with authenticated management protocols
   such as NETCONF [RFC6241] and RESTCONF [RFC8040], over their secure
   transport mappings.  Deployments MUST authenticate peers and protect
   confidentiality and integrity.  The Network Configuration Access
   Control Model [RFC8341] can restrict both data access and operations.

Xu, et al.                 Expires 3 May 2027                  [Page 35]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   All configuration under /routing/resilient-next-hop-groups is
   sensitive.  Changing membership or next-hop addresses can redirect
   traffic; changing weights, bucket-count, or policy can move active
   flows; setting idle-timer to zero or reducing unbalanced-timer can
   permit disruptive movement.  These writes MUST be restricted to
   authorized administrators.

   The rebalance action bypasses recovery timers and can move active
   traffic.  Authorization MUST be checked independently of its
   generation precondition.  Repeated reads, rejected actions,
   notifications, and large bucket-table retrievals can consume
   resources; servers MUST impose suitable request, work, and
   notification limits.  A generation token prevents a stale decision
   from executing; it is not a secret or an authorization credential.

   Operational next hops, interface bindings, bucket assignments, member
   transitions, and error diagnostics reveal topology and traffic-
   handling policy.  Access SHOULD be limited to authorized consumers.
   Implementations SHOULD avoid exposing secrets or unnecessary internal
   details in diagnostic strings.  Malicious liveness inputs can induce
   repeated repair, so liveness sources and their authentication require
   deployment-specific protection.

11.  IANA Considerations

11.1.  XML Namespace

   IANA is requested to register urn:ietf:params:xml:ns:yang:ietf-
   resilient-next-hop-group in the IETF XML Registry [RFC3688].
   Registrant Contact: The IESG.  XML: N/A; the requested URI is an XML
   namespace.

11.2.  YANG Module

   IANA is requested to register the module under the YANG Module Names
   registry [RFC6020]: Name: ietf-resilient-next-hop-group; Namespace:
   urn:ietf:params:xml:ns:yang:ietf-resilient-next-hop-group; Prefix:
   rnhg; Reference: RFC XXXX.  No assignment or working group ownership
   is implied before approval.

12.  Normative References

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

Xu, et al.                 Expires 3 May 2027                  [Page 36]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   [RFC3688]  Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688,
              DOI 10.17487/RFC3688, January 2004,
              <https://www.rfc-editor.org/info/rfc3688>.

   [RFC6020]  Bjorklund, M., Ed., "YANG - A Data Modeling Language for
              the Network Configuration Protocol (NETCONF)", RFC 6020,
              DOI 10.17487/RFC6020, October 2010,
              <https://www.rfc-editor.org/info/rfc6020>.

   [RFC6241]  Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed.,
              and A. Bierman, Ed., "Network Configuration Protocol
              (NETCONF)", RFC 6241, DOI 10.17487/RFC6241, June 2011,
              <https://www.rfc-editor.org/info/rfc6241>.

   [RFC7950]  Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language",
              RFC 7950, DOI 10.17487/RFC7950, August 2016,
              <https://www.rfc-editor.org/info/rfc7950>.

   [RFC8040]  Bierman, A., Bjorklund, M., and K. Watsen, "RESTCONF
              Protocol", RFC 8040, DOI 10.17487/RFC8040, January 2017,
              <https://www.rfc-editor.org/info/rfc8040>.

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

   [RFC8341]  Bierman, A. and M. Bjorklund, "Network Configuration
              Access Control Model", STD 91, RFC 8341,
              DOI 10.17487/RFC8341, March 2018,
              <https://www.rfc-editor.org/info/rfc8341>.

   [RFC8342]  Bjorklund, M., Schoenwaelder, J., Shafer, P., Watsen, K.,
              and R. Wilton, "Network Management Datastore Architecture
              (NMDA)", RFC 8342, DOI 10.17487/RFC8342, March 2018,
              <https://www.rfc-editor.org/info/rfc8342>.

   [RFC8343]  Bjorklund, M., "A YANG Data Model for Interface
              Management", RFC 8343, DOI 10.17487/RFC8343, March 2018,
              <https://www.rfc-editor.org/info/rfc8343>.

   [RFC8349]  Lhotka, L., Lindem, A., and Y. Qu, "A YANG Data Model for
              Routing Management (NMDA Version)", RFC 8349,
              DOI 10.17487/RFC8349, March 2018,
              <https://www.rfc-editor.org/info/rfc8349>.

   [RFC9911]  Schoenwaelder, J., Ed., "Common YANG Data Types",
              RFC 9911, DOI 10.17487/RFC9911, December 2025,
              <https://www.rfc-editor.org/info/rfc9911>.

Xu, et al.                 Expires 3 May 2027                  [Page 37]
Internet-Draft          Resilient Next-Hop Groups           October 2026

13.  Informative References

   [GRIBI]    OpenConfig, "gRIBI Service Definition",
              <https://github.com/openconfig/gribi/blob/master/v1/proto/
              service/gribi.proto>.

   [I-D.ietf-bess-weighted-hrw]
              Mohanty, S. R., Mishra, M. P., Lindem, A., Sajassi, A.,
              and J. Drake, "Weighted HRW and its applications", Work in
              Progress, Internet-Draft, draft-ietf-bess-weighted-hrw-02,
              7 July 2025, <https://datatracker.ietf.org/doc/html/draft-
              ietf-bess-weighted-hrw-02>.

   [LINUX]    Linux contributors, "Resilient Next-hop Groups",
              <https://docs.kernel.org/networking/nexthop-group-
              resilient.html>.

   [OC-AFT]   OpenConfig, "OpenConfig Abstract Forwarding Table Common
              Model, revision 2026-10-04",
              <https://github.com/openconfig/public/blob/master/release/
              models/aft/openconfig-aft-common.yang>.

   [OC-STATIC]
              OpenConfig, "OpenConfig Network Instance Static Model,
              revision 2026-05-12",
              <https://github.com/openconfig/public/blob/master/release/
              models/network-instance/openconfig-network-instance-
              static.yang>.

   [RFC2992]  Hopps, C., "Analysis of an Equal-Cost Multi-Path
              Algorithm", RFC 2992, DOI 10.17487/RFC2992, November 2000,
              <https://www.rfc-editor.org/info/rfc2992>.

   [RFC8340]  Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams",
              BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018,
              <https://www.rfc-editor.org/info/rfc8340>.

   [RFC9907]  Bierman, A., Boucadair, M., Ed., and Q. Wu, "Guidelines
              for Authors and Reviewers of Documents Containing YANG
              Data Models", BCP 216, RFC 9907, DOI 10.17487/RFC9907,
              March 2026, <https://www.rfc-editor.org/info/rfc9907>.

   [SAI-NHG]  Open Compute Project, "Switch Abstraction Interface: Next
              Hop Group API",
              <https://github.com/opencomputeproject/SAI/blob/master/
              inc/sainexthopgroup.h>.

Xu, et al.                 Expires 3 May 2027                  [Page 38]
Internet-Draft          Resilient Next-Hop Groups           October 2026

Authors' Addresses

   Bohua Xu
   China Unicom
   Beijing
   100000
   China
   Email: xubh15@chinaunicom.cn

   Chang Liu
   China Unicom
   Beijing
   100000
   China
   Email: liuc131@chinaunicom.cn

   Yu Zhou
   China Unicom
   Beijing
   100000
   China
   Email: zhouy739@chinaunicom.cn

   Chenyang Wen
   China Unicom
   Beijing
   100000
   China
   Email: wency15@chinaunicom.cn

   Wei Cheng
   Centec
   Suzhou
   215000
   China
   Email: chengw@centec.com

   Junjie Wang
   Centec
   Suzhou
   215000
   China
   Email: wangjj@centec.com

Xu, et al.                 Expires 3 May 2027                  [Page 39]
Internet-Draft          Resilient Next-Hop Groups           October 2026

   Mingyu Wu
   Centec
   Suzhou
   215000
   China
   Email: wumy@centec.com

   Yongtao Yang
   Centec
   Suzhou
   215000
   China
   Email: yangyt@centec.com

Xu, et al.                 Expires 3 May 2027                  [Page 40]