[Rift] RIFT YANG model review, iteration rift-yang-tree200706

Bruno Rijsman <brunorijsman@gmail.com> Fri, 10 July 2020 11:33 UTC

Return-Path: <brunorijsman@gmail.com>
X-Original-To: rift@ietfa.amsl.com
Delivered-To: rift@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 44D873A09D8 for <rift@ietfa.amsl.com>; Fri, 10 Jul 2020 04:33:59 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.098
X-Spam-Level:
X-Spam-Status: No, score=-2.098 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MisFLVNZqLoT for <rift@ietfa.amsl.com>; Fri, 10 Jul 2020 04:33:56 -0700 (PDT)
Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 0B5523A09D6 for <rift@ietf.org>; Fri, 10 Jul 2020 04:33:55 -0700 (PDT)
Received: by mail-ed1-x52b.google.com with SMTP id z17so4378036edr.9 for <rift@ietf.org>; Fri, 10 Jul 2020 04:33:55 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:message-id:mime-version:subject:date:in-reply-to:cc:to :references; bh=NgwoMzam6SxrO0JA6zJbk1qW+dxoWhtv8GwFNT67gHw=; b=qAP7sipArJxTCYh1IF8j1flIymvfTdPa8oFXIh2R3mOe4XXHdrKs0FPQNpZJTU61Fo gLQfpFUrYZv4NwTdQN/BywEytsvKWL8KyWLfBll0AUYZJVUqUThwhuq4XR/Vkem1eCPI fBmKlyX00EaanooxcZw8sNjsM4QhABjQ+Qlh2wiu/M/xHBiQ5OtPI3rJOp4nypGnUvYF xR2Kje2Ny202hWzW8YhGq29I6I4jCG6H1ezgMR9iZSk4ZgNn6N+S62AUawZDFMFGQGJy TQsorJjwLQJ0aQba8wSNhjidiMh9bKrcKYfEQNTGdKe0zkv+uyAgVjiOMMFlBwUz/OFC L+Uw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:mime-version:subject:date :in-reply-to:cc:to:references; bh=NgwoMzam6SxrO0JA6zJbk1qW+dxoWhtv8GwFNT67gHw=; b=N/R84MVc8wJwtRxg4376fM6ngHcNXgE8jAm+9vzLtDax9i1sctfW2xI28QR1h6HO4u tAUx3cpSciGUMzFCY34J5XyNSLRussKBqrrQY9nNvv/1XmlefrYY3LLRgb3zg3C7sj54 DMV+MIH/BQCLgq6Kxww2rdkiGbForYAHo+q5WpU8B6YatA8XgIAk154J1Wlqx5WNtCn8 iH6GTknbtoC7Katgh2MIqSt3xnO8L8d8lgemm+j7NZKYA5jh8ERMxazfKgfSedZ8Kbh2 5Zhzb/lvNJbZ0DaOv4tQ42jF2tvgozHHGWm5vJ9XBf76ugRW6pcMohSr6UwA9DnXoonx 24Yw==
X-Gm-Message-State: AOAM533x0vuugoZqETtcQfXp08ksSvZswtEfk+FQr3CLlO9XuRkZJv5u OSqqQTWhtV4NUjRbkSakyki+itwqvP0=
X-Google-Smtp-Source: ABdhPJyS/DdqZclRWMN6Z9VYhOUJ+5eDZfj/k2kgHC8P8GrvHG2Uhv2TXfL/jizmekwuUbWdQI5+HQ==
X-Received: by 2002:aa7:de05:: with SMTP id h5mr74898568edv.275.1594380834129; Fri, 10 Jul 2020 04:33:54 -0700 (PDT)
Received: from [192.168.178.192] (82-73-48-167.cable.dynamic.v4.ziggo.nl. [82.73.48.167]) by smtp.gmail.com with ESMTPSA id p9sm3513975ejd.50.2020.07.10.04.33.52 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Jul 2020 04:33:53 -0700 (PDT)
From: Bruno Rijsman <brunorijsman@gmail.com>
Message-Id: <E3AA4708-C8AC-4A22-8B7A-0CD6CD1945DE@gmail.com>
Content-Type: multipart/alternative; boundary="Apple-Mail=_6AF6465B-7A6F-45BF-9FBD-EF780D9E29DB"
Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\))
Date: Fri, 10 Jul 2020 13:33:52 +0200
In-Reply-To: <32F1F103-D95A-4A43-AA25-3180916B5F2E@gmail.com>
Cc: rift@ietf.org
To: zhang.zheng@zte.com.cn
References: <BF881FFF-9AFC-48F0-BC86-AF8069DE957A@juniper.net, 1B02CCAE-000D-4EA3-8240-4EA7CFCA3AEF@gmail.com> <202007061506485460169@zte.com.cn> <D300B738-343B-48FE-976C-A04F23E3CE1B@gmail.com> <32F1F103-D95A-4A43-AA25-3180916B5F2E@gmail.com>
X-Mailer: Apple Mail (2.3608.80.23.2.2)
Archived-At: <https://mailarchive.ietf.org/arch/msg/rift/Zrda2mLVTqm56cfctGHUK0-4ayo>
Subject: [Rift] RIFT YANG model review, iteration rift-yang-tree200706
X-BeenThere: rift@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Discussion of Routing in Fat Trees <rift.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/rift>, <mailto:rift-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/rift/>
List-Post: <mailto:rift@ietf.org>
List-Help: <mailto:rift-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/rift>, <mailto:rift-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 10 Jul 2020 11:33:59 -0000

Hi Sandy,

Here is the next review iteration (for rift-yang-tree200706).

Once again, there is more reviewing to be done, but I am talking it step by step in bite-sized chunks.

— Bruno

module: ietf-rift
  augment /rt:routing/rt:control-plane-protocols/rt:control-plane-protocol:
    +--rw rift!
       +--rw node
          +--rw name?                        string

Node needs to be a list (indexed by name); in the case of multi-instance RIFT there can be more than one RIFT node per RIFT engine. That also implies that name is the key and hence mandatory. This brings us to:

+--rw node* [name]
   +--rw name   string


          +--ro level?                       level
          +--rw system-id                    system-id
          +--rw pod?                         uint32
          +--rw configured-level?            level
          +--rw overload?                    boolean
          +--ro protocol-minor-version       uint16
          +--ro hierarchy-indications?       enumeration
          +--rw flood-reduction?             boolean
          +--rw nonce-increasing-interval?   uint16
          +--rw maximum-nonce-delta?         uint8 {nonce-delta-adjust}?
          +--rw rx-lie-multicast-address
          |  +--rw ipv4?   inet:ipv4-address
          |  +--rw ipv6?   inet:ipv6-address
          +--rw tx-lie-multicast-address
          |  +--rw ipv4?   inet:ipv4-address
          |  +--rw ipv6?   inet:ipv6-address
          +--rw lie-tx-port?                 inet:port-number
          +--rw global-link-capabilities
          |  +--rw bfd?                     boolean
          |  +--rw v4-forwarding-capable?   boolean
          +--rw rx-flood-port?               inet:port-number
          +--rw holdtime?                    rt-types:timer-value-seconds16
          +--rw tide-generation-interval?    rt-types:timer-value-seconds16
          +--rw tie-security-key-id?         uint32
          +--rw interface* [name]
          |  +--ro local-link-id?                  linkid-type

We should be consistent. Whenever an attribute foo is both advertised to a neighbor vs receive from a neighbor, either do (a) or (b) or (c) or (d) below. The current YANG model does a mixture of all of these:
(a) Call it foo under interface and also foo (same name) under neighbor (e.g. interface cost vs neighbor cost). The context (interface vs neighbor) determines whether it is local/sent/advertised vs remote/received.
(b) Call it advertised-foo under interface and received-foo under neighbor (e.g. advertised-lie-tie-addresses vs received-lie-tie-addresses)
(c) Call it local-foo under interface and remote-foo under neighbor (e.g. local-link-id vs remote-link-id).
(d) Nest foo in advertised-in-lies for the interface, and nest foo in received-in-lies for the neighbor (e.g. interface advertised-in-lies you-are-flood-repeater vs neighbor received-in-lies you-are-flood-repeater)

I prefer (a) but I could live with (b) or (c) or (d) as well, as long as we are consistent. For example, if we pick (a) you would remove local- from local-link-id.

          |  +--rw name                            if:interface-ref
          |  +--rw metric?                         uint32

Rename metric to cost, as discussed in separate e-mail.

          |  +--rw advertised-lie-tie-addresses
          |  |  +--ro rx-lie-source-address
          |  |  |  +--ro ipv4?   inet:ipv4-address
          |  |  |  +--ro ipv6?   inet:ipv6-address
          |  |  +--ro flooding-source-address
          |  |     +--ro ipv4?   inet:ipv4-address
          |  |     +--ro ipv6?   inet:ipv6-address
          |  +--ro direction-type?                 enumeration
          |  +--ro was-the-last-lie-accepted?      boolean

I suggest adding an optional last-lie-reject-reason (string) that explains why the LIE was rejected if was-the-last-lie-accepted is false.

          |  +--rw advertised-in-lies

YANG question: does it make sense to have a read-write container with only read-only attributes?

          |  |  +--ro you-are-flood-repeater?        boolean
          |  |  +--ro not-a-ztp-offer?               boolean
          |  |  +--ro you-are-sending-too-quickly?   boolean
          |  +--rw link-capabilities
          |  |  +--rw bfd?                     boolean
          |  |  +--rw v4-forwarding-capable?   boolean
          |  +--rw state?                          enumeration

State should be read-only and mandatory. The adjacency (and hence the interface) always has an operational (not a configured) state: one-way, two-way, three-way, or multiple-neighbors.

          |  +--ro neighbor

Neighbor should be optional. In state ONE_WAY there is no neighbor.

          |     +--ro name?                         string
          |     +--ro level?                        level
          |     +--ro system-id                     system-id
          |     +--ro pod?                          uint32
          |     +--ro protocol-version?             uint16
          |     +--ro address-families
          |     |  +--ro address-family* [address-family]
          |     |     +--ro address-family    iana-rt-types:address-family
          |     +--ro received-lie-tie-addresses
          |     |  +--ro rx-lie-source-address
          |     |  |  +--ro ipv4?   inet:ipv4-address
          |     |  |  +--ro ipv6?   inet:ipv6-address
          |     |  +--ro flooding-source-address
          |     |     +--ro ipv4?   inet:ipv4-address
          |     |     +--ro ipv6?   inet:ipv6-address
          |     +--ro remote-id?                    uint32
          |     +--ro cost?                         uint32
          |     +--ro metric?                       uint32
          |     +--ro bandwidth?                    uint32
          |     +--ro flood-reduction?              boolean
          |     +--ro received-link-capabilities
          |     |  +--ro bfd?                     boolean
          |     |  +--ro v4-forwarding-capable?   boolean
          |     +--ro received-from-lies

If we end up picking (d) in the comment near the top, rename received-from-lies => received-in-lies

          |     |  +--ro you-are-flood-repeater?        boolean
          |     |  +--ro not-a-ztp-offer?               boolean
          |     |  +--ro you-are-sending-too-quickly?   boolean
          |     +--ro tx-flood-port?                inet:port-number
          |     +--ro bfd-up?                       boolean
          |     +--ro outer-security-key-id?        uint8
          +--ro miscabled-links*             linkid-type
          +--rw (algorithm-type)?
          |  +--:(spf)
          |  +--:(all-path)

I don't know this :(foo) syntax. What does it mean?

          +--ro hal?                         level
          +--ro vol-list
          |  +--ro vol* [system-id]
          |     +--ro offered-level?   level
          |     +--ro name?            string
          |     +--ro level?           level
          |     +--ro system-id        system-id
          |     +--ro pod?             uint32


There is one sent offer per neighbor, and one received offer per neighbor (see example output of RIFT-Python "show node" below)

At this point in the YANG model we are already in the neighbor container. This implies that 
(a) We only need to keep track of one single sent offer and one received offer (not a list of offers indexed by system-id).
(b) We already know the system-id of the neighbor (it is an attribute of the neighbor container)
(c) For both sent and received offers, we need to keep track of the level and not-a-ztp-offer
(d) FOr the received offer, we additionally need to keep track of whether it is the best offer (in the Python implementation I keep track of some additional information for easier debugging, e.g. whether or not it was removed from consideration and if so why, once again see output below).

All of this leads to the following possible YANG model:

          +--rw interface* [name]
          |  +--ro local-link-id?                    linkid-type
          |  +--rw name                              if:interface-ref
          |  +--ro neighbor
          |     +--ro name?                           string
          |     +--ro sent-offer
          |     |  +--ro level                        level
          |     |  +--ro not-a-ztp-offer              boolean
          |     +--ro received-offer
          |     |  +--ro level                        level
          |     |  +--ro not-a-ztp-offer              boolean
          |     |  +--ro best                         boolean
          |     |  +--ro removed-from-consideration   boolean
          |     |  +--ro removal-reason?              string


agg_101> show node
Node:
+---------------------------------------+------------------+
| Name                                  | agg_101          |
[...]
+---------------------------------------+------------------+

Received Offers:
+-------------+-----------+-------+-----------------+-----------+-------+------------+---------+----------------+
| Interface   | System ID | Level | Not A ZTP Offer | State     | Best  | Best 3-Way | Removed | Removed Reason |
+-------------+-----------+-------+-----------------+-----------+-------+------------+---------+----------------+
| if_101_1    | 1         | 24    | False           | THREE_WAY | True  | True       | False   |                |
+-------------+-----------+-------+-----------------+-----------+-------+------------+---------+----------------+
| if_101_1001 | 1001      | 0     | False           | THREE_WAY | False | False      | True    | Level is leaf  |
+-------------+-----------+-------+-----------------+-----------+-------+------------+---------+----------------+
| if_101_1002 | 1002      | 0     | False           | THREE_WAY | False | False      | True    | Level is leaf  |
+-------------+-----------+-------+-----------------+-----------+-------+------------+---------+----------------+
| if_101_2    | 2         | 24    | False           | THREE_WAY | False | False      | False   |                |
+-------------+-----------+-------+-----------------+-----------+-------+------------+---------+----------------+

Sent Offers:
+-------------+-----------+-------+-----------------+-----------+
| Interface   | System ID | Level | Not A ZTP Offer | State     |
+-------------+-----------+-------+-----------------+-----------+
| if_101_1    | 101       | 23    | True            | THREE_WAY |
+-------------+-----------+-------+-----------------+-----------+
| if_101_1001 | 101       | 23    | False           | THREE_WAY |
+-------------+-----------+-------+-----------------+-----------+
| if_101_1002 | 101       | 23    | False           | THREE_WAY |
+-------------+-----------+-------+-----------------+-----------+
| if_101_2    | 101       | 23    | True            | THREE_WAY |
+-------------+-----------+-------+-----------------+-----------+

(Reviewed until here in this review iteration).

          +--rw instance-label?              uint32
          +--ro database
          |  +--ro ties* [direction-type originator tie-type tie-number]
          |     +--ro direction-type          enumeration
          |     +--ro originator              system-id
          |     +--ro tie-type                enumeration
          |     +--ro tie-number              uint32
          |     +--ro seq?                    uint64
          |     +--ro origination-time?       uint32
          |     +--ro origination-lifetime?   uint32
          |     +--ro node
          |     |  +--ro name?              string
          |     |  +--ro level?             level
          |     |  +--ro system-id          system-id
          |     |  +--ro pod?               uint32
          |     |  +--ro flood-reduction?   boolean
          |     |  +--ro overload?          boolean
          |     |  +--ro startup-time?      uint64
          |     |  +--ro neighbors* [system-id]
          |     |  |  +--ro name?                         string
          |     |  |  +--ro level?                        level
          |     |  |  +--ro system-id                     system-id
          |     |  |  +--ro pod?                          uint32
          |     |  |  +--ro address-families
          |     |  |  |  +--ro address-family* [address-family]
          |     |  |  |     +--ro address-family    iana-rt-types:address-family
          |     |  |  +--ro received-lie-tie-addresses
          |     |  |  |  +--ro rx-lie-source-address
          |     |  |  |  |  +--ro ipv4?   inet:ipv4-address
          |     |  |  |  |  +--ro ipv6?   inet:ipv6-address
          |     |  |  |  +--ro flooding-source-address
          |     |  |  |     +--ro ipv4?   inet:ipv4-address
          |     |  |  |     +--ro ipv6?   inet:ipv6-address
          |     |  |  +--ro remote-id?                    uint32
          |     |  |  +--ro cost?                         uint32
          |     |  |  +--ro metric?                       uint32
          |     |  |  +--ro bandwidth?                    uint32
          |     |  |  +--ro flood-reduction?              boolean
          |     |  |  +--ro received-link-capabilities
          |     |  |  |  +--ro bfd?                     boolean
          |     |  |  |  +--ro v4-forwarding-capable?   boolean
          |     |  |  +--ro received-from-lies
          |     |  |  |  +--ro you-are-flood-repeater?        boolean
          |     |  |  |  +--ro not-a-ztp-offer?               boolean
          |     |  |  |  +--ro you-are-sending-too-quickly?   boolean
          |     |  |  +--ro tx-flood-port?                inet:port-number
          |     |  |  +--ro bfd-up?                       boolean
          |     |  |  +--ro outer-security-key-id?        uint8
          |     |  +--ro miscabled-links*   linkid-type
          |     +--ro prefix
          |        +--ro prefix?              inet:ip-prefix
          |        +--ro (type)?
          |        |  +--:(prefix)
          |        |  +--:(positive-disaggregation)
          |        |  +--:(negative-disaggregation)
          |        |  +--:(external)
          |        |  +--:(positive-external-disaggregation)
          |        |  +--:(pgp)
          |        +--ro metric?              uint32
          |        +--ro tags*                uint64
          |        +--ro monotonic-clock
          |        |  +--ro prefix-sequence-type
          |        |     +--ro timestamp         ieee802-1as-timestamp-type
          |        |     +--ro transaction-id?   uint8
          |        +--ro loopback?            boolean
          |        +--ro directly-attached?   boolean
          |        +--ro from-link?           linkid-type
          +--ro kv-store
             +--ro kvs* [kvs-index]
                +--ro kvs-index    uint32
                +--ro kvs-tie
                   +--ro direction-type?         enumeration
                   +--ro originator?             system-id
                   +--ro tie-type?               enumeration
                   +--ro tie-number?             uint32
                   +--ro seq?                    uint64
                   +--ro origination-time?       uint32
                   +--ro origination-lifetime?   uint32
                   +--ro key-value
                      +--ro key?     uint16
                      +--ro value?   uint32

  notifications:
    +---n error-set
       +--ro tie-level-error
       |  +--ro direction-type?         enumeration
       |  +--ro originator?             system-id
       |  +--ro tie-type?               enumeration
       |  +--ro tie-number?             uint32
       |  +--ro seq?                    uint64
       |  +--ro origination-time?       uint32
       |  +--ro origination-lifetime?   uint32
       +--ro neighbor-error
          +--ro neighbor* [system-id]
             +--ro name?                         string
             +--ro level?                        level
             +--ro system-id                     system-id
             +--ro pod?                          uint32
             +--ro protocol-version?             uint16
             +--ro address-families
             |  +--ro address-family* [address-family]
             |     +--ro address-family    iana-rt-types:address-family
             +--ro received-lie-tie-addresses
             |  +--ro rx-lie-source-address
             |  |  +--ro ipv4?   inet:ipv4-address
             |  |  +--ro ipv6?   inet:ipv6-address
             |  +--ro flooding-source-address
             |     +--ro ipv4?   inet:ipv4-address
             |     +--ro ipv6?   inet:ipv6-address
             +--ro remote-id?                    uint32
             +--ro cost?                         uint32
             +--ro metric?                       uint32
             +--ro bandwidth?                    uint32
             +--ro flood-reduction?              boolean
             +--ro received-link-capabilities
             |  +--ro bfd?                     boolean
             |  +--ro v4-forwarding-capable?   boolean
             +--ro received-from-lies
             |  +--ro you-are-flood-repeater?        boolean
             |  +--ro not-a-ztp-offer?               boolean
             |  +--ro you-are-sending-too-quickly?   boolean
             +--ro tx-flood-port?                inet:port-number
             +--ro bfd-up?                       boolean
             +--ro outer-security-key-id?        uint8