Re: [netmod] leafref to multi-key list: can only use current() in 2nd leafref

"Sterne, Jason (Nokia - CA/Ottawa)" <jason.sterne@nokia.com> Fri, 21 May 2021 20:57 UTC

Return-Path: <jason.sterne@nokia.com>
X-Original-To: netmod@ietfa.amsl.com
Delivered-To: netmod@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id D2F003A2058 for <netmod@ietfa.amsl.com>; Fri, 21 May 2021 13:57:45 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.598
X-Spam-Level:
X-Spam-Status: No, score=-2.598 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.698, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=nokia.onmicrosoft.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 iAu15QPPKoOb for <netmod@ietfa.amsl.com>; Fri, 21 May 2021 13:57:40 -0700 (PDT)
Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2116.outbound.protection.outlook.com [40.107.223.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id A6B0A3A2057 for <netmod@ietf.org>; Fri, 21 May 2021 13:57:40 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hWcRkAj3DLVZgjCDWeHx2hRts8zLz5TYE2USBIPUKIgCnfmhZ3EHEmOhGvG6JT+DW42GXO+aFhgNIaSSCgNxE/ipEU3rPnZCa+c0EwhVyJB1LaTipEkWHVk2/AS7DF3quLWfsfsD3O+PKhpRW31lqvZVz603di/6ZntrTsdu693rvthkEJuaBmFQ1q22gz3+8TssLh30tqizYTATTDvi2vl6mEM0TMjAtgFY/WVhQMnDJYyB3SLRfP7q/CiNTeDS8RQ4SVh/VX+FPlz5FlxT1PZMtoF4EvKqo+JZD/FbFuIjTf5XA0gtdlerHFZGnQ4JcgDVuoDxU+d+hsZMRs0IrA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3zKwKi3+r6QrjMUcpycvuaMhs5zN28DrPuLbIux185g=; b=d/qVDFQlAfYxBUxlaVPk+Yi7yxQ3uScxKLK7AVPrYbFW4mfeKeW99T3gZDVxbbxSHSiB/KVzPEVtqFH31qel+tl6Z6suNZWjfGO3jjZvvrtfqmb8oO9VVBBrBRn7pMSC0RMIPxam4Vohb79QMtWlr+NK8krZ2/jPsl+n4GaaIP1KwtdoyaaMUROP0JVXrOoUqEiqw4/lDcieww9gSjYjdkWdaJotCicjl6s11tVMsGvPLhTrqEzJl8+vsjX6TAUmTrvfZyz+iWCVKuYVboMVTi35NpMfZGG/xfeVUNECnFxePCUucT2xMUspFetMT5kvq1H4NrXydLuewNoza0WxVQ==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nokia.com; dmarc=pass action=none header.from=nokia.com; dkim=pass header.d=nokia.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nokia.onmicrosoft.com; s=selector1-nokia-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3zKwKi3+r6QrjMUcpycvuaMhs5zN28DrPuLbIux185g=; b=UFq5jhJEa8gM7yUCKxfyx9FslYKOX1c1ILvCsK+06w+iubJyo4a4Zt5kZA7pA0gHwDVk0lKtnEYx5PxCAHmzavtSNMOJdZBpK6hMkCnViZGBNzpab5bJAaSYdXZrZDvXiBfHggPQ4UsPM16yzpx9mlpOhlvkW8fHLUXGQdY5t3M=
Received: from DM6PR08MB5084.namprd08.prod.outlook.com (2603:10b6:5:41::29) by DM6PR08MB5401.namprd08.prod.outlook.com (2603:10b6:5:15::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4150.25; Fri, 21 May 2021 20:57:37 +0000
Received: from DM6PR08MB5084.namprd08.prod.outlook.com ([fe80::616e:7de0:be27:e9b1]) by DM6PR08MB5084.namprd08.prod.outlook.com ([fe80::616e:7de0:be27:e9b1%3]) with mapi id 15.20.4129.035; Fri, 21 May 2021 20:57:37 +0000
From: "Sterne, Jason (Nokia - CA/Ottawa)" <jason.sterne@nokia.com>
To: Jan Lindblad <janl@tail-f.com>
CC: "netmod@ietf.org" <netmod@ietf.org>
Thread-Topic: [netmod] leafref to multi-key list: can only use current() in 2nd leafref
Thread-Index: AQHXThbTra6CVlStU0iOuvWc5LUrtaruapWg
Date: Fri, 21 May 2021 20:57:37 +0000
Message-ID: <DM6PR08MB5084458954E40172AB626C669B299@DM6PR08MB5084.namprd08.prod.outlook.com>
References: <DM6PR08MB5084F0CB6B01D6212491D91E9B2A9@DM6PR08MB5084.namprd08.prod.outlook.com> <350EFD59-094F-48F5-951A-02E279859474@tail-f.com>
In-Reply-To: <350EFD59-094F-48F5-951A-02E279859474@tail-f.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach:
X-MS-TNEF-Correlator:
authentication-results: tail-f.com; dkim=none (message not signed) header.d=none;tail-f.com; dmarc=none action=none header.from=nokia.com;
x-originating-ip: [23.233.24.194]
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: d10d8919-87e4-4ba2-dceb-08d91c9b10a8
x-ms-traffictypediagnostic: DM6PR08MB5401:
x-microsoft-antispam-prvs: <DM6PR08MB540145AD87C7E6983460C2D09B299@DM6PR08MB5401.namprd08.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:9508;
x-ms-exchange-senderadcheck: 1
x-microsoft-antispam: BCL:0;
x-microsoft-antispam-message-info: mipXi6dsBpL3LxaTUinbqIBFVp+9t24uD1QhuOgCtGuY/a9vmTVUVP8k9dlJCKW2VTgvUEktdAvx98eVm4S546CN7MN1/A8VbZow42KtAGGSIFrfXnOYv5DsdJPJa1PT3MCORsukNgD+BY71KEdlEVIcTGGEGRUrEHgK7jSyeiL9G1hmOM8L9Ng2c/ILmyfaP6NPC25B0nIuYO2QDpnh0SUgM2taKYEEDmwqkATgNRKhqUgv8NKpp3lKDHt2yiD2mQtOY+KDpiHBQy3H6XZoKvF9NMMi7zF7L/d2hvxhjKF3J3jh4Psp36dsct0Y0ibH8IBjmHCxOjqGVt2ZM2u4Ke+3Y/HhJTQ8mwRyY4Pz1qYDN5NdN/AvsCgr8U1j223eAVtLkRCYJqFoQMhGE/49blY6qVyFyVGbQM7g/016oLRgfR+deG5MptbJhvaY7U4pcvaSeFUpKteaA8E6nzquXnifDS5Lvvlf6fLbIaTTuocGQw0luEHMuFtlYby7fjWTdfobn9IofyG8ur0JyXJrUqZ6VP454x5/1ucO7RKfQiqy9jjHBtYxGXkBN/FRXwLYQcQDKrFYVmU8nP+CfCjB+x9FSGskfg72NEzfVD3bHX9CHjjUeM/tvSYQTJeifoQhpJrDboH7w27vH2hcmbYk3hemN4anVHdxox5UJBEfJC8BzfBuZDo7yApHfG6l8+ikqGS9iAoB2J11tMPydqNjBfHXlNRr43KuDeIUBazI11g=
x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DM6PR08MB5084.namprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(346002)(376002)(396003)(39860400002)(136003)(366004)(966005)(86362001)(52536014)(55016002)(66574015)(316002)(26005)(166002)(76116006)(66556008)(9686003)(66446008)(6916009)(71200400001)(122000001)(6506007)(8676002)(83380400001)(66946007)(53546011)(64756008)(66476007)(38100700002)(33656002)(2906002)(5660300002)(7696005)(186003)(4326008)(8936002)(478600001); DIR:OUT; SFP:1102;
x-ms-exchange-antispam-messagedata: HUditgqiJkv+XKH2VREulF+oHD8UmeICkzmsXer5MCohq+5xaBFsegGIrCgoKeDJ+YuVuRXvtF9gke72PnZbPk5FCCB9G+7UZT41lZw1fwTf0w9Kiv7KO+Af0Al6YJxwHkl9TAwcJhMkA2s0w/LV7cjA/wLNJGh+dkn03UuGK40Ob77CE6YyZvhk08vrMlw+ARXxk6M1CYEQMRGU3cXHFOdgn44ExveItxYaPitUT4dNbuAaMeVogdtuxpBrBcvqQxne4JSnBImXRwR7SmAIaUSVFUjChTPJoGyLtTDHLV9LrUq9N/3crT8ZG4ARhnKrmcWg7y6ukAWN/09zRKUFpjQ9R3Jp0FPFrQ5CkYMIHMRF0zsN/MbzBMDRVV20NrYK0ondjo88vEaRmW2B7MbN53zMCKGzFs+O8lbRdkNaspVXrVKOTszhTr7wm1wSfNZ2syVJM4hN2j3dQDFSsKdlonciOkTAFZXVCArkLfWRknIQhzBi6v6Vt7kJmIWiMvw0bVydQ3rx8/Yor8XdgOXCuo+W8d4rL+MMmr/YxcKmiaYXslJCNA8gVKe3mygJVmTljZV7SLJo0XyeugRJCcaDp2xoyDAH+6oOaX0+q4F7ogCujTSGL8v/3R/nbFjggjgy2X1PumAsjPB8MRVU4SAMIJRTVU34AdrJqzdxk0FekRtY3cRU1UIJCXidpNmTkDDX8yjpqAyoQwBRLwPE/Is1ndlgUpTGkdBwHgVe4ao7Joha1EmTqnnsLIDzPCVFP6szEByYI2QGeMYlERo1Ek7MSzKEnoEIHvOZIwLBHDVSMGPJz0Y4RjUJzgPqtZruw1u96YzYGm9wdogIFrOqT0cCnI3u81in66EdNQir/6UuG+iXViPfVXqTM9cGetsFqGvpXA+TjSgOYYjA1XxaTsgSoMPwxdEbsXMqtMOUnurQ0oUchGViCJgAZB3w1YfWFpOBcYmX3mFqw05wtZ1YuMkQMbA408bxj4zYsUwWCdYc0/in+n9ogwapBpUpNqPS9m/iknSmce0oexKiRGQCIUWkmDNmyFNMtxzrSW3of1FrCDNIV21G0kseDlyn9jlN1qkpHoWFGIXBG9quCMNTY4tGDAD8u4nLUDsFzxMfOlLx1sxOe4nS0LX9aHzhYruRjn42yInkbng0jAPU/J+ICAm3N7S9hrSKSln00+459RI//AF6KCZWfV/KWjvRArA0mHKYsii+YFN3eGgkMwwHJoaHzVvDwlBAV7BLSHilHh6hvWwNFabG8JRf4RjQ6/9ZSTKnQqWf4VTafq3Cn8djnkylas/k269WLevHP+6adoLgSOqUa3JcNWMwMiJmhb804qJz
x-ms-exchange-transport-forked: True
Content-Type: multipart/alternative; boundary="_000_DM6PR08MB5084458954E40172AB626C669B299DM6PR08MB5084namp_"
MIME-Version: 1.0
X-OriginatorOrg: nokia.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-AuthSource: DM6PR08MB5084.namprd08.prod.outlook.com
X-MS-Exchange-CrossTenant-Network-Message-Id: d10d8919-87e4-4ba2-dceb-08d91c9b10a8
X-MS-Exchange-CrossTenant-originalarrivaltime: 21 May 2021 20:57:37.3423 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 5d471751-9675-428d-917b-70f44f9630b0
X-MS-Exchange-CrossTenant-mailboxtype: HOSTED
X-MS-Exchange-CrossTenant-userprincipalname: LcL5TdyoRYmTC1Rmm2uzyXop+47KnSrXMz+pMgCfEmQRfmuq7jBL71ybJ7fT3USXBgtGB3YFao3LluW+nQz3oQ==
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR08MB5401
Archived-At: <https://mailarchive.ietf.org/arch/msg/netmod/Oi2CydDRjCSrkZpYTQfWhUjwGsM>
Subject: Re: [netmod] leafref to multi-key list: can only use current() in 2nd leafref
X-BeenThere: netmod@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: NETMOD WG list <netmod.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netmod>, <mailto:netmod-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netmod/>
List-Post: <mailto:netmod@ietf.org>
List-Help: <mailto:netmod-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netmod>, <mailto:netmod-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 21 May 2021 20:57:46 -0000

Thanks for the excellent detailed response Jan.

I see what you are saying. I was familiar with the first part (the need for the "current()" in the predicates to bind things together), but unsure whether predicates in *all* the leafrefs was somehow invalid (I wasn't seeing that anywhere in other models).

We're taking a closer look back at our specific problem now that we know this is valid. It looks like it may be something else on our side (and yangLint was correct to complain).

Jason


From: Jan Lindblad <janl@tail-f.com>
Sent: Friday, May 21, 2021 3:57 AM
To: Sterne, Jason (Nokia - CA/Ottawa) <jason.sterne@nokia.com>
Cc: netmod@ietf.org
Subject: Re: [netmod] leafref to multi-key list: can only use current() in 2nd leafref

Hi Jason,

In any examples I've seen where a YANG model contains a set of leafrefs to a multi-key list, or to a list key within a list, the "current()" xpath function is only in the 2nd leafref and never the first.

Yes. When you want to model a reference to a particular list instance somewhere, you need to use one leafref for each key in the path from the referrer to the referenced instance. But that is not enough. From the second leafref on, you also need to bind the keys together, so that the leafrefs identify a single instance.

Let me give you an example (shortened, stolen from Network Programmability with YANG, chapter 3). Let's say we have a list of books keyed by title and delivery format:

list book {
  key "title format";
  leaf title { type string; }
  leaf format { type bookformat; }
}

And the following three instances exist:

TITLE                                   FORMAT
--------------------------------------------------------------
The Hitchhiker’s Guide to the Galaxy    paperback
The Hitchhiker’s Guide to the Galaxy    mp3
The Neverending Story                   paperback
A naïve refererrer might use:

grouping book-reference {
  leaf title {
    type leafref {
      path "/book/title";
    }
  }
  leaf format {
    type leafref {
      path "/book/format";
    }
  }
}

This modeling is not very good because this allows the operator to fill in a reference to "The Neverending Story" + "mp3". Both leafref values are valid according to the YANG, they both exist in that list. They just don't identify any single instance.

This is why the leafrefs have to be bound together, so that they only allow values among the instances pointed out by the previous/other leafrefs. For example like this:

grouping book-reference {
  leaf title {
    type leafref {
      path "/book/title";
    }
  }
  leaf format {
    type leafref {
      path "/book[title=current()/../title]/format";
    }
  }
}

This makes "format" only able to take on values that exist for the books pointed out by title. In the case of "The Neverending Story", that would only be "paperback". For "The Hitchhiker’s Guide to the Galaxy", that would be "paperback" or "mp3".

If you had a list with three keys, the binding would get a bit longer:

grouping basic-mylist-reference {
  leaf ref1 {
    type leafref {
      path "../../mylist/key1";
    }
  }
  leaf ref2 {
    type leafref {
      path "../../mylist[key1=current()/../ref1]/key2";
    }
  }
  leaf ref3 {
    type leafref {
      path "../../mylist[key1=current()/../ref1][key2=current()/../ref2]/key3";
    }
  }
}

From a logical validity point of view, you could of course add those predicates (filters) to every leafref, like this:

grouping not-optimal-mylist-reference {
  leaf ref1 {
    type leafref {
      path "../../mylist[key2=current()/../ref2][key3=current()/../ref3]/key1";
    }
  }
  leaf ref2 {
    type leafref {
      path "../../mylist[key1=current()/../ref1][key3=current()/../ref3]/key2";
    }
  }
  leaf ref3 {
    type leafref {
      path "../../mylist[key1=current()/../ref1][key2=current()/../ref2]/key3";
    }
  }
}

I would advice against this, however. You would gain some symmetry and verbosity, but on the bottom line it would cost you two things:
- Performace. If the YANG validator in question is implemented using an XPath evaluator, you have just doubled the validation work for this part of the model.
- Step by step guidance. If the validity of each of the values depend on all the others, it's hard for a system to convey to the operator what the valid values are for each ref leaf. Using the basic-mylist-reference above (or modern-mylist-reference below), systems could allow ref1 values to be tab-completed or presented in a drop down. Once filled in, the same could be done with ref2, and then ref3. Very convenient for the operator. That flow is lost with the non-optimal-mylist-reference.

A more modern way of binding the keys together is to use the YANG 1.1 XPath function deref(). It reduces the verbosity and sharpens the modelers intent a bit. Using deref, you would get this:

grouping modern-mylist-reference {
  leaf ref1 {
    type leafref {
      path "../../mylist/key1";
    }
  }
  leaf ref2 {
    type leafref {
      path "deref(../ref1)/../key2";
    }
  }
  leaf ref3 {
    type leafref {
      path "deref(../ref2)/../key3";
    }
  }
}

Readable, efficient and with a good flow if you ask me.

You did not share the details around the issues with yanglint instance data validation, so it's hard to say what went wrong there.

Best Regards,
/jan



EXAMPLE A - OpenConfig  ACL model

      list acl-set {
        key "name type";

… snip …

  grouping interface-ingress-acl-config {
    description
      "Configuration data for per-interface ingress ACLs";

    leaf set-name {
      type leafref {
        path "../../../../../../acl-sets/acl-set/config/name";
      }
      description
        "Reference to the ACL set name applied on ingress";
    }

    leaf type {
      type leafref {
        path "../../../../../../acl-sets/acl-set[name=current()/../set-name]" +
          "/config/type";
      }
      description
        "Reference to the ACL set type applied on ingress";
    }
  }

We've tried this type of 2-leaf leafref in some models, and yangLint complains (validating instance data) if we instead changed the first one to the following (this is just an illustrative example, we actually did a similar thing with our own models, not actually with this OpenCOnfig model):

    leaf set-name {
      type leafref {
        path "../../../../../../acl-sets/acl-set[type=current()/../type]/config/name";

      }
      description
        "Reference to the ACL set name applied on ingress";
    }

I'm not sure I understand why this wouldn't work. When all is said and done, both leafrefs would be satisfied if this is applied atomically. But maybe it is some sort of circular chicken-and-egg problem in resolving the value spaces ?

I suspect I'm missing some basic understanding here since:
- Other examples of 2-part leafrefs always only use current() in the 2nd leafref, and
- yangLint complains about this (with instance data)

Rgds,
Jason


_______________________________________________
netmod mailing list
netmod@ietf.org<mailto:netmod@ietf.org>
https://www.ietf.org/mailman/listinfo/netmod