From e6899cc3f5bb7a3b712316ee2c015cd5406b56d5 Mon Sep 17 00:00:00 2001 From: Jonathan Ben-Avraham Date: Sat, 7 Nov 2020 21:44:59 +0200 Subject: [PATCH 1/4] Additional documentation for test scripts Added documentation in comments in test scripts, added example site.sh, moved evaluation of site.sh later in lib.sh to allow site.sh to override more lib.sh variables. --- .gitignore | 9 +++++++-- test/all.sh | 24 +++++++++++++++++++----- test/lib.sh | 44 ++++++++++++++++++++++++++------------------ test/site.sh | 22 ++++++++++++++++++++++ test/sum.sh | 27 +++++++++++++++++++++------ 5 files changed, 95 insertions(+), 31 deletions(-) create mode 100644 test/site.sh diff --git a/.gitignore b/.gitignore index dd071d13..5c1ef35e 100644 --- a/.gitignore +++ b/.gitignore @@ -51,10 +51,15 @@ build-root/*.rpm build-root/rpmbuild util/clixon_util_datastore -util/clixon_util_insert +util/clixon_util_grpc util/clixon_util_json +util/clixon_util_path +util/clixon_util_regexp +util/clixon_util_socket +util/clixon_util_ssl util/clixon_util_stream util/clixon_util_xml +util/clixon_util_xml_mod util/clixon_util_xpath util/clixon_util_yang @@ -62,4 +67,4 @@ test/config.sh test/site.sh test/vagrant/site.mk test/cicd/site.mk -doc/html \ No newline at end of file +doc/html diff --git a/test/all.sh b/test/all.sh index 97fdc7be..93a825b5 100755 --- a/test/all.sh +++ b/test/all.sh @@ -1,13 +1,27 @@ #!/usr/bin/env bash -# Run, eg as: -# ./all.sh 2>&1 | tee test.log # break on first test +# Run test_*.sh tests, stop on error, verbose logging, no pass/fail summary. +# +# This script requires the user to be in the sudo group. +# +# The 'pattern' variable determines which test files to execute. +# By default, run all the tests in the test_*.sh files in this directory. -# Pattern to run tests, default is all, but you may want to narrow it down : ${pattern:=test_*.sh} +# You can specify tests files to exclude using the 'SKIPLIST' variable in a +# site.sh file. See example in README.md. Files excluded by the 'SKIPLIST' +# variable have precedence over files included by the 'pattern' variable. + +# This script does not take arguments, so if arguments exist, print the Usage +# in http://docopt.org/ format. if [ $# -gt 0 ]; then - echo "usage: $0 # detailed logs and stop on first error. Use pattern=\"\" $0 to" - echo " Use pattern= $0 to narrow down test cases" + echo "Usage:" + echo " $0 # Run all 'test_*.sh' files" + echo " pattern= $0 # Run only files matching the pattern" + echo "" + echo "Example:" + echo " ${0} 2>&1 | tee test.log # Run all tests, output to 'test.log'" + echo " pattern=test_feature.sh ${0} # Run only the tests in 'test_feature.sh'" exit -1 fi diff --git a/test/lib.sh b/test/lib.sh index eb3aa166..d4a85452 100755 --- a/test/lib.sh +++ b/test/lib.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash # Define test functions. +# See numerous configuration variables later on in this file that you can set +# in the environment or the site.sh file. The definitions in the site.sh file +# override +# # Create working dir as variable "dir" # The functions are somewhat wildgrown, a little too many: # - expectfn @@ -17,8 +21,11 @@ # Testfile (not including path) : ${testfile:=$(basename $0)} -# Add test to this list that you dont want run -# Typically add them in your site file +# SKIPLIST lists the filenames of the test files that you do *not* want to run. +# The format is a whitespace separated list of filenames. Specify the SKIPLIST +# either in the shell environment or in the site.sh file. Any SKIPLIST specified +# in site.sh overrides a SKIPLIST specified in the environment. If not specified +# in either the environment or the site.sh, then the default SKIPLIST is empty. : ${SKIPLIST:=""} # Some tests (openconfig/yang_models) just test for the cli to return a version @@ -34,21 +41,6 @@ if [ -f ./config.sh ]; then fi fi -# Site file, an example of this file in README.md -if [ -f ./site.sh ]; then - . ./site.sh - if [ $? -ne 0 ]; then - return -1 # skip - fi - # test skiplist. - for f in $SKIPLIST; do - if [ "$testfile" = "$f" ]; then - echo "...skipped (see site.sh)" - return -1 # skip - fi - done -fi - # Test number from start : ${testnr:=0} @@ -122,7 +114,6 @@ fi # Standard IETF RFC yang files. : ${IETFRFC=../yang/standard} -#: ${IETFRFC=$YANGMODELS/standard/ietf/RFC} # Backend user BUSER=clicon @@ -141,6 +132,23 @@ BUSER=clicon : ${clixon_backend:=clixon_backend} +# Source the site-specific definitions for test script variables, if site.sh +# exists. The variables defined in site.sh override any variables of the same +# names in the environment in the current execution. +if [ -f ./site.sh ]; then + . ./site.sh + if [ $? -ne 0 ]; then + return -1 # skip + fi + # test skiplist. + for f in $SKIPLIST; do + if [ "$testfile" = "$f" ]; then + echo "...skipped (see site.sh)" + return -1 # skip + fi + done +fi + dir=/var/tmp/$0 if [ ! -d $dir ]; then mkdir $dir diff --git a/test/site.sh b/test/site.sh new file mode 100644 index 00000000..5ea335a7 --- /dev/null +++ b/test/site.sh @@ -0,0 +1,22 @@ +#!#/bin/sh +# Use this file to specify local site-specific env variables, or tests to +# skip. This file is sourced by lib.sh +# +# Add test filenames that you do not want to run to the SKIPLIST variable. The +# SKIPLIST is evaluated as a Bash glob in lib.sh, so you can use it to skip +# files from the begining of the file list up to a pattern by specifying an +# appropriate glob such as "test_[a-n]*\.sh". +# +# The SKIPLIST has precedence over the 'pattern' variable that you can use to +# specify included file when running the various test scripts such as "all.sh". +#SKIPLIST="test_[a-t]*\.sh test_openconfig.sh test_yangmodels.sh" +# +# Parse yang openconfig models from https://github.com/openconfig/public +#OPENCONFIG=/usr/local/share/openconfig/public +# +# Parse yangmodels from https://github.com/YangModels/yang +#YANGMODELS=/usr/local/share/yangmodels +# +# Specify alternative directory for the standard IETF RFC yang files. +#IETFRFC=$YANGMODELS/standard/ietf/RFC + diff --git a/test/sum.sh b/test/sum.sh index dce42c68..af988ad5 100755 --- a/test/sum.sh +++ b/test/sum.sh @@ -1,15 +1,30 @@ #!/usr/bin/env bash -# Run, eg as: -# ./sum.sh # to run all tests and print +# Run test_*.sh tests, continue on error, no logging, print pass/fail summary. +# +# This script requires the user to be in the sudo group. +# +# The 'pattern' variable determines which test files are executed. +# By default, run all the tests in the test_*.sh files in this directory. +: ${pattern:=test_*.sh} + +# You can specify tests files to exclude using the 'SKIPLIST' variable in a +# site.sh file. See example in README.md. Files excluded by the 'SKIPLIST' +# variable have precedence over files included by the 'pattern' variable. + +# This script does not take arguments, so if arguments exist, print the Usage +# in http://docopt.org/ format. if [ $# -gt 0 ]; then - echo "usage: $0 # pipe to dev/null and continue on error" + echo "Usage:" + echo " ${0} # Run all 'test_*.sh' files" + echo " pattern= ${0} # Run only files matching the pattern" + echo "" + echo "Example:" + echo " ${0} 2>&1 | tee test.log # Run all tests, output to 'test.log'" + echo " pattern=test_feature.sh ${0} # Run only the tests in 'test_feature.sh'" exit -1 fi -# Pattern to run tests, default is all, but you may want to narrow it down -: ${pattern:=test_*.sh} - err=0 for testfile in $pattern; do # For lib.sh the variable must be called testfile echo "Running $testfile" From a1f54d71ac4dda86995045544671badc6f835fe8 Mon Sep 17 00:00:00 2001 From: Jonathan Ben-Avraham Date: Sat, 7 Nov 2020 22:06:05 +0200 Subject: [PATCH 2/4] Update yang/mandatory files for rfc8527 compliance Updated the yang/mandatory files and test scripts for rfc8527. --- docker/main/README.md | 2 +- example/main/clixon-example@2020-03-11.yang | 3 + test/test_feature.sh | 4 +- test/test_netconf.sh | 2 +- test/test_perf_state.sh | 9 +- test/test_restconf.sh | 8 +- test/test_restconf_jukebox.sh | 6 +- test/test_upgrade_quit.sh | 2 +- yang/mandatory/Makefile.in | 5 +- .../mandatory/ietf-datastores@2018-02-14.yang | 117 ++++ .../mandatory/ietf-inet-types@2013-07-15.yang | 457 -------------- .../mandatory/ietf-inet-types@2020-07-06.yang | 589 ++++++++++++++++++ .../ietf-yang-library@2016-06-21.yang | 242 ------- .../ietf-yang-library@2019-01-04.yang | 544 ++++++++++++++++ 14 files changed, 1274 insertions(+), 716 deletions(-) create mode 100644 yang/mandatory/ietf-datastores@2018-02-14.yang delete mode 100644 yang/mandatory/ietf-inet-types@2013-07-15.yang create mode 100644 yang/mandatory/ietf-inet-types@2020-07-06.yang delete mode 100644 yang/mandatory/ietf-yang-library@2016-06-21.yang create mode 100644 yang/mandatory/ietf-yang-library@2019-01-04.yang diff --git a/docker/main/README.md b/docker/main/README.md index b5da8f8d..6e3395a8 100644 --- a/docker/main/README.md +++ b/docker/main/README.md @@ -56,7 +56,7 @@ As restconf using curl on exposed port 80: "ietf-restconf:restconf": { "data": {}, "operations": {}, - "yang-library-version": "2016-06-21" + "yang-library-version": "2019-01-04" } } ``` diff --git a/example/main/clixon-example@2020-03-11.yang b/example/main/clixon-example@2020-03-11.yang index a86fe7fc..0e03ccc3 100644 --- a/example/main/clixon-example@2020-03-11.yang +++ b/example/main/clixon-example@2020-03-11.yang @@ -26,6 +26,9 @@ module clixon-example { import iana-if-type { prefix ianaift; } + import ietf-datastores { + prefix ds; + } /* Example interface type for tests, local callbacks, etc */ identity eth { diff --git a/test/test_feature.sh b/test/test_feature.sh index 0f64eab0..fa18053e 100755 --- a/test/test_feature.sh +++ b/test/test_feature.sh @@ -221,7 +221,7 @@ fi fi # false new "netconf module ietf-inet-types" -expect="ietf-inet-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-inet-typesimplement" +expect="ietf-inet-types2020-07-06urn:ietf:params:xml:ns:yang:ietf-inet-typesimplement" match=`echo "$ret" | grep --null -Go "$expect"` if [ -z "$match" ]; then err "$expect" "$ret" @@ -248,7 +248,7 @@ match=`echo "$ret" | grep --null -Go "$expect"` if [ -z "$match" ]; then err "$expect" "$ret" fi -expect="ietf-yang-library2016-06-21urn:ietf:params:xml:ns:yang:ietf-yang-libraryimplement" +expect="ietf-yang-library2019-01-04urn:ietf:params:xml:ns:yang:ietf-yang-libraryimplement" match=`echo "$ret" | grep --null -Go "$expect"` if [ -z "$match" ]; then err "$expect" "$ret" diff --git a/test/test_netconf.sh b/test/test_netconf.sh index 36c70c64..d1397296 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -75,7 +75,7 @@ new "Netconf snd hello with prefix" expecteof "$clixon_netconf -qf $cfg" 0 "urn:ietf:params:netconf:base:1.0]]>]]>" '^$' new "netconf snd + rcv hello" -expecteof "$clixon_netconf -f $cfg" 0 "urn:ietf:params:netconf:base:1.0]]>]]>" "^urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:yang-library:1.0?revision=2016-06-21&module-set-id=42urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:startup:1.0urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:notification:1.0[0-9]*]]>]]>$" +expecteof "$clixon_netconf -f $cfg" 0 "urn:ietf:params:netconf:base:1.0]]>]]>" "^urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:startup:1.0urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:notification:1.0[0-9]*]]>]]>$" new "netconf rcv hello, disable RFC7895/ietf-yang-library" expecteof "$clixon_netconf -f $cfg -o CLICON_MODULE_LIBRARY_RFC7895=0" 0 "]]>]]>" "^urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:startup:1.0urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:notification:1.0[0-9]*]]>]]>]]>]]>$" diff --git a/test/test_perf_state.sh b/test/test_perf_state.sh index 020353d6..466a54dc 100755 --- a/test/test_perf_state.sh +++ b/test/test_perf_state.sh @@ -139,7 +139,9 @@ expecteof "time -p $clixon_netconf -qf $cfg" 0 "] new "netconf get test single req" sel="/ex:interfaces/ex:a[ex:name='foo']/ex:b/ex:interface[ex:name='e1']" msg="]]>]]>" -expecteof "$clixon_netconf -qf $cfg" 0 "$msg" "^fooe1ex:ethtrueup]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$msg" "fooe1trueup]]>]]>" + +# '^fooe1ex:ethtrueup]]>]]>$" new "netconf get $perfreq single reqs" { time -p for (( i=0; i<$perfreq; i++ )); do @@ -150,7 +152,7 @@ done | $clixon_netconf -qf $cfg > /dev/null; } 2>&1 | awk '/real/ {print $2}' # RESTCONF get new "restconf get test single req" -expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/example:interfaces/a=foo/b/interface=e1)" 0 "HTTP/1.1 200 OK" '{"example:interface":\[{"name":"e1","type":"ex:eth","enabled":true,"status":"up"}\]}' +expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/example:interfaces/a=foo/b/interface=e1)" 0 "HTTP/1.1 200 OK" '{"example:interface":\[{"name":"e1","enabled":true,"status":"up"}\]}' new "restconf get $perfreq single reqs" #curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e67 @@ -166,7 +168,8 @@ edit interfaces a foo b interface e1 show state xml EOF new "cli get test single req" -expectpart "$($clixon_cli -F $fin -f $cfg)" 0 "e1" "ex:eth" "true" "up$" +expectpart "$($clixon_cli -F $fin -f $cfg)" 0 "e1" "true" "up$" +#expectpart "$($clixon_cli -F $fin -f $cfg)" 0 "e1" "ex:eth" "true" "up$" new "cli get $perfreq single reqs" { time -p for (( i=0; i<$perfreq; i++ )); do diff --git a/test/test_restconf.sh b/test/test_restconf.sh index ede1139c..92de6fa7 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -66,11 +66,11 @@ new "restconf root discovery. RFC 8040 3.1 (xml+xrd)" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/.well-known/host-meta)" 0 'HTTP/1.1 200 OK' "" "" "" new "restconf get restconf resource. RFC 8040 3.3 (json)" -expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf)" 0 'HTTP/1.1 200 OK' '{"ietf-restconf:restconf":{"data":{},"operations":{},"yang-library-version":"2016-06-21"}}' +expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf)" 0 'HTTP/1.1 200 OK' '{"ietf-restconf:restconf":{"data":{},"operations":{},"yang-library-version":"2019-01-04"}}' new "restconf get restconf resource. RFC 8040 3.3 (xml)" # Get XML instead of JSON? -expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 'HTTP/1.1 200 OK' '2016-06-21' +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 'HTTP/1.1 200 OK' '2019-01-04' # Should be alphabetically ordered new "restconf get restconf/operations. RFC8040 3.3.2 (json)" @@ -85,11 +85,11 @@ if [ -z "$match" ]; then fi new "restconf get restconf/yang-library-version. RFC8040 3.3.3" -expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/yang-library-version)" 0 'HTTP/1.1 200 OK' '{"yang-library-version":"2016-06-21"}' +expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/yang-library-version)" 0 'HTTP/1.1 200 OK' '{"yang-library-version":"2019-01-04"}' new "restconf get restconf/yang-library-version. RFC8040 3.3.3 (xml)" ret=$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/yang-library-version) -expect="2016-06-21" +expect="2019-01-04" match=`echo $ret | grep --null -Eo "$expect"` if [ -z "$match" ]; then err "$expect" "$ret" diff --git a/test/test_restconf_jukebox.sh b/test/test_restconf_jukebox.sh index 29908abe..e316cb71 100755 --- a/test/test_restconf_jukebox.sh +++ b/test/test_restconf_jukebox.sh @@ -91,17 +91,17 @@ fi new "B.1.1. Retrieve the Top-Level API Resource root" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/xrd+xml' $RCPROTO://localhost/.well-known/host-meta)" 0 "HTTP/1.1 200 OK" "Content-Type: application/xrd+xml" "" "" "" -d='{"ietf-restconf:restconf":{"data":{},"operations":{},"yang-library-version":"2016-06-21"}}' +d='{"ietf-restconf:restconf":{"data":{},"operations":{},"yang-library-version":"2019-01-04"}}' new "B.1.1. Retrieve the Top-Level API Resource /restconf json" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" "$d" new "B.1.1. Retrieve the Top-Level API Resource /restconf xml (not in RFC)" -expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+xml" '2016-06-21' +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+xml" '2019-01-04' # This just catches the header and the jukebox module, the RFC has foo and bar which # seems wrong to recreate new "B.1.2. Retrieve the Server Module Information" -expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},' +expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-datastores","revision":"2018-02-14","namespace":"urn:ietf:params:xml:ns:yang:ietf-datastores","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2020-07-06","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},{"name":"ietf-netconf","revision":"2011-06-01","namespace":"urn:ietf:params:xml:ns:netconf:base:1.0","feature":\["candidate","validate","xpath"\],"conformance-type":"implement"},{"name":"ietf-restconf","revision":"2017-01-26","namespace":"urn:ietf:params:xml:ns:yang:ietf-restconf","conformance-type":"implement"},{"name":"ietf-restconf-monitoring","revision":"2017-01-26","namespace":"urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring","conformance-type":"implement"},{"name":"ietf-yang-library","revision":"2019-01-04","namespace":"urn:ietf:params:xml:ns:yang:ietf-yang-library","conformance-type":"implement"},{"name":"ietf-yang-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-yang-types","conformance-type":"implement"}\]}}' new "B.1.3. Retrieve the Server Capability Information" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' 'urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=expliciturn:ietf:params:restconf:capability:depth diff --git a/test/test_upgrade_quit.sh b/test/test_upgrade_quit.sh index 7c4a132c..9b80868d 100755 --- a/test/test_upgrade_quit.sh +++ b/test/test_upgrade_quit.sh @@ -301,7 +301,7 @@ cat < $dir/startup_db EOF -MODSTATE='0clixon-lib2020-04-23http://clicon.org/libietf-inet-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-inet-typesietf-netconf2011-06-01urn:ietf:params:xml:ns:netconf:base:1.0ietf-restconf2017-01-26urn:ietf:params:xml:ns:yang:ietf-restconfietf-yang-library2016-06-21urn:ietf:params:xml:ns:yang:ietf-yang-libraryietf-yang-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-yang-typesinterfaces2018-02-20urn:example:interfaces' +MODSTATE='0clixon-lib2020-04-23http://clicon.org/libietf-datastores2018-02-14urn:ietf:params:xml:ns:yang:ietf-datastoresietf-inet-types2020-07-06urn:ietf:params:xml:ns:yang:ietf-inet-typesietf-netconf2011-06-01urn:ietf:params:xml:ns:netconf:base:1.0ietf-restconf2017-01-26urn:ietf:params:xml:ns:yang:ietf-restconfietf-yang-library2019-01-04urn:ietf:params:xml:ns:yang:ietf-yang-libraryietf-yang-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-yang-typesinterfaces2018-02-20urn:example:interfaces' XML='e0First interfaceethup54326.4328458765e1ethdown' diff --git a/yang/mandatory/Makefile.in b/yang/mandatory/Makefile.in index eb7f016c..32c78337 100644 --- a/yang/mandatory/Makefile.in +++ b/yang/mandatory/Makefile.in @@ -41,13 +41,14 @@ datarootdir = @datarootdir@ # See also YANG_INSTALLDIR for the clixon-specific yang files YANG_INSTALLDIR = @YANG_INSTALLDIR@ -YANGSPECS = ietf-inet-types@2013-07-15.yang +YANGSPECS = ietf-inet-types@2020-07-06.yang YANGSPECS += ietf-netconf@2011-06-01.yang YANGSPECS += ietf-netconf-acm@2018-02-14.yang YANGSPECS += ietf-restconf@2017-01-26.yang YANGSPECS += ietf-restconf-monitoring@2017-01-26.yang -YANGSPECS += ietf-yang-library@2016-06-21.yang +YANGSPECS += ietf-yang-library@2019-01-04.yang YANGSPECS += ietf-yang-types@2013-07-15.yang +YANGSPECS += ietf-datastores@2018-02-14.yang all: diff --git a/yang/mandatory/ietf-datastores@2018-02-14.yang b/yang/mandatory/ietf-datastores@2018-02-14.yang new file mode 100644 index 00000000..9e875ab6 --- /dev/null +++ b/yang/mandatory/ietf-datastores@2018-02-14.yang @@ -0,0 +1,117 @@ +module ietf-datastores { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-datastores"; + prefix ds; + + organization + "IETF Network Modeling (NETMOD) Working Group"; + + contact + "WG Web: + + WG List: + + Author: Martin Bjorklund + + + Author: Juergen Schoenwaelder + + + Author: Phil Shafer + + + Author: Kent Watsen + + + Author: Rob Wilton + "; + + description + "This YANG module defines a set of identities for identifying + datastores. + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + 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 Simplified 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 8342 + (https://www.rfc-editor.org/info/rfc8342); see the RFC itself + for full legal notices."; + + revision 2018-02-14 { + description + "Initial revision."; + reference + "RFC 8342: Network Management Datastore Architecture (NMDA)"; + } + + /* + * Identities + */ + + identity datastore { + description + "Abstract base identity for datastore identities."; + } + + identity conventional { + base datastore; + description + "Abstract base identity for conventional configuration + datastores."; + } + + identity running { + base conventional; + description + "The running configuration datastore."; + } + + identity candidate { + base conventional; + description + "The candidate configuration datastore."; + } + + identity startup { + base conventional; + description + "The startup configuration datastore."; + } + + identity intended { + base conventional; + description + "The intended configuration datastore."; + } + + identity dynamic { + base datastore; + description + "Abstract base identity for dynamic configuration datastores."; + } + + identity operational { + base datastore; + description + "The operational state datastore."; + } + + /* + * Type definitions + */ + + typedef datastore-ref { + type identityref { + base datastore; + } + description + "A datastore identity reference."; + } +} diff --git a/yang/mandatory/ietf-inet-types@2013-07-15.yang b/yang/mandatory/ietf-inet-types@2013-07-15.yang deleted file mode 100644 index ef3b9d47..00000000 --- a/yang/mandatory/ietf-inet-types@2013-07-15.yang +++ /dev/null @@ -1,457 +0,0 @@ - module ietf-inet-types { - - namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; - prefix "inet"; - - organization - "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; - - contact - "WG Web: - WG List: - - WG Chair: David Kessens - - - WG Chair: Juergen Schoenwaelder - - - Editor: Juergen Schoenwaelder - "; - - description - "This module contains a collection of generally useful derived - YANG data types for Internet addresses and related things. - - Copyright (c) 2013 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - 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 Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 6991; see - the RFC itself for full legal notices."; - - revision 2013-07-15 { - description - "This revision adds the following new data types: - - ip-address-no-zone - - ipv4-address-no-zone - - ipv6-address-no-zone"; - reference - "RFC 6991: Common YANG Data Types"; - } - - revision 2010-09-24 { - description - "Initial revision."; - reference - "RFC 6021: Common YANG Data Types"; - } - - /*** collection of types related to protocol fields ***/ - - typedef ip-version { - type enumeration { - enum unknown { - value "0"; - description - "An unknown or unspecified version of the Internet - protocol."; - } - enum ipv4 { - value "1"; - description - "The IPv4 protocol as defined in RFC 791."; - } - enum ipv6 { - value "2"; - description - "The IPv6 protocol as defined in RFC 2460."; - } - } - description - "This value represents the version of the IP protocol. - - In the value set and its semantics, this type is equivalent - to the InetVersion textual convention of the SMIv2."; - reference - "RFC 791: Internet Protocol - RFC 2460: Internet Protocol, Version 6 (IPv6) Specification - RFC 4001: Textual Conventions for Internet Network Addresses"; - } - - typedef dscp { - type uint8 { - range "0..63"; - } - description - "The dscp type represents a Differentiated Services Code Point - that may be used for marking packets in a traffic stream. - In the value set and its semantics, this type is equivalent - to the Dscp textual convention of the SMIv2."; - reference - "RFC 3289: Management Information Base for the Differentiated - Services Architecture - RFC 2474: Definition of the Differentiated Services Field - (DS Field) in the IPv4 and IPv6 Headers - RFC 2780: IANA Allocation Guidelines For Values In - the Internet Protocol and Related Headers"; - } - - typedef ipv6-flow-label { - type uint32 { - range "0..1048575"; - } - description - "The ipv6-flow-label type represents the flow identifier or Flow - Label in an IPv6 packet header that may be used to - discriminate traffic flows. - - In the value set and its semantics, this type is equivalent - to the IPv6FlowLabel textual convention of the SMIv2."; - reference - "RFC 3595: Textual Conventions for IPv6 Flow Label - RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; - } - - typedef port-number { - type uint16 { - range "0..65535"; - } - description - "The port-number type represents a 16-bit port number of an - Internet transport-layer protocol such as UDP, TCP, DCCP, or - SCTP. Port numbers are assigned by IANA. A current list of - all assignments is available from . - - Note that the port number value zero is reserved by IANA. In - situations where the value zero does not make sense, it can - be excluded by subtyping the port-number type. - In the value set and its semantics, this type is equivalent - to the InetPortNumber textual convention of the SMIv2."; - reference - "RFC 768: User Datagram Protocol - RFC 793: Transmission Control Protocol - RFC 4960: Stream Control Transmission Protocol - RFC 4340: Datagram Congestion Control Protocol (DCCP) - RFC 4001: Textual Conventions for Internet Network Addresses"; - } - - /*** collection of types related to autonomous systems ***/ - - typedef as-number { - type uint32; - description - "The as-number type represents autonomous system numbers - which identify an Autonomous System (AS). An AS is a set - of routers under a single technical administration, using - an interior gateway protocol and common metrics to route - packets within the AS, and using an exterior gateway - protocol to route packets to other ASes. IANA maintains - the AS number space and has delegated large parts to the - regional registries. - - Autonomous system numbers were originally limited to 16 - bits. BGP extensions have enlarged the autonomous system - number space to 32 bits. This type therefore uses an uint32 - base type without a range restriction in order to support - a larger autonomous system number space. - - In the value set and its semantics, this type is equivalent - to the InetAutonomousSystemNumber textual convention of - the SMIv2."; - reference - "RFC 1930: Guidelines for creation, selection, and registration - of an Autonomous System (AS) - RFC 4271: A Border Gateway Protocol 4 (BGP-4) - RFC 4001: Textual Conventions for Internet Network Addresses - RFC 6793: BGP Support for Four-Octet Autonomous System (AS) - Number Space"; - } - - /*** collection of types related to IP addresses and hostnames ***/ - - typedef ip-address { - type union { - type inet:ipv4-address; - type inet:ipv6-address; - } - description - "The ip-address type represents an IP address and is IP - version neutral. The format of the textual representation - implies the IP version. This type supports scoped addresses - by allowing zone identifiers in the address format."; - reference - "RFC 4007: IPv6 Scoped Address Architecture"; - } - - typedef ipv4-address { - type string { - pattern - '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' - + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' - + '(%[\p{N}\p{L}]+)?'; - } - description - "The ipv4-address type represents an IPv4 address in - dotted-quad notation. The IPv4 address may include a zone - index, separated by a % sign. - - The zone index is used to disambiguate identical address - values. For link-local addresses, the zone index will - typically be the interface index number or the name of an - interface. If the zone index is not present, the default - zone of the device will be used. - - The canonical format for the zone index is the numerical - format"; - } - - typedef ipv6-address { - type string { - pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' - + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' - + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' - + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' - + '(%[\p{N}\p{L}]+)?'; - pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' - + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' - + '(%.+)?'; - } - description - "The ipv6-address type represents an IPv6 address in full, - mixed, shortened, and shortened-mixed notation. The IPv6 - address may include a zone index, separated by a % sign. - - The zone index is used to disambiguate identical address - values. For link-local addresses, the zone index will - typically be the interface index number or the name of an - interface. If the zone index is not present, the default - zone of the device will be used. - - The canonical format of IPv6 addresses uses the textual - representation defined in Section 4 of RFC 5952. The - canonical format for the zone index is the numerical - format as described in Section 11.2 of RFC 4007."; - reference - "RFC 4291: IP Version 6 Addressing Architecture - RFC 4007: IPv6 Scoped Address Architecture - RFC 5952: A Recommendation for IPv6 Address Text - Representation"; - } - - typedef ip-address-no-zone { - type union { - type inet:ipv4-address-no-zone; - type inet:ipv6-address-no-zone; - } - description - "The ip-address-no-zone type represents an IP address and is - IP version neutral. The format of the textual representation - implies the IP version. This type does not support scoped - addresses since it does not allow zone identifiers in the - address format."; - reference - "RFC 4007: IPv6 Scoped Address Architecture"; - } - - typedef ipv4-address-no-zone { - type inet:ipv4-address { - pattern '[0-9\.]*'; - } - description - "An IPv4 address without a zone index. This type, derived from - ipv4-address, may be used in situations where the zone is - known from the context and hence no zone index is needed."; - } - - typedef ipv6-address-no-zone { - type inet:ipv6-address { - pattern '[0-9a-fA-F:\.]*'; - } - description - "An IPv6 address without a zone index. This type, derived from - ipv6-address, may be used in situations where the zone is - known from the context and hence no zone index is needed."; - reference - "RFC 4291: IP Version 6 Addressing Architecture - RFC 4007: IPv6 Scoped Address Architecture - RFC 5952: A Recommendation for IPv6 Address Text - Representation"; - } - - typedef ip-prefix { - type union { - type inet:ipv4-prefix; - type inet:ipv6-prefix; - } - description - "The ip-prefix type represents an IP prefix and is IP - version neutral. The format of the textual representations - implies the IP version."; - } - - typedef ipv4-prefix { - type string { - pattern - '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' - + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' - + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; - } - description - "The ipv4-prefix type represents an IPv4 address prefix. - The prefix length is given by the number following the - slash character and must be less than or equal to 32. - - A prefix length value of n corresponds to an IP address - mask that has n contiguous 1-bits from the most - significant bit (MSB) and all other bits set to 0. - - The canonical format of an IPv4 prefix has all bits of - the IPv4 address set to zero that are not part of the - IPv4 prefix."; - } - - typedef ipv6-prefix { - type string { - pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' - + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' - + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' - + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' - + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; - pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' - + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' - + '(/.+)'; - } - description - "The ipv6-prefix type represents an IPv6 address prefix. - The prefix length is given by the number following the - slash character and must be less than or equal to 128. - - A prefix length value of n corresponds to an IP address - mask that has n contiguous 1-bits from the most - significant bit (MSB) and all other bits set to 0. - - The IPv6 address should have all bits that do not belong - to the prefix set to zero. - - The canonical format of an IPv6 prefix has all bits of - the IPv6 address set to zero that are not part of the - IPv6 prefix. Furthermore, the IPv6 address is represented - as defined in Section 4 of RFC 5952."; - reference - "RFC 5952: A Recommendation for IPv6 Address Text - Representation"; - } - - /*** collection of domain name and URI types ***/ - - typedef domain-name { - type string { - pattern - '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' - + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' - + '|\.'; - length "1..253"; - } - description - "The domain-name type represents a DNS domain name. The - name SHOULD be fully qualified whenever possible. - - Internet domain names are only loosely specified. Section - 3.5 of RFC 1034 recommends a syntax (modified in Section - 2.1 of RFC 1123). The pattern above is intended to allow - for current practice in domain name use, and some possible - future expansion. It is designed to hold various types of - domain names, including names used for A or AAAA records - (host names) and other records, such as SRV records. Note - that Internet host names have a stricter syntax (described - in RFC 952) than the DNS recommendations in RFCs 1034 and - 1123, and that systems that want to store host names in - schema nodes using the domain-name type are recommended to - adhere to this stricter standard to ensure interoperability. - - The encoding of DNS names in the DNS protocol is limited - to 255 characters. Since the encoding consists of labels - prefixed by a length bytes and there is a trailing NULL - byte, only 253 characters can appear in the textual dotted - notation. - - The description clause of schema nodes using the domain-name - type MUST describe when and how these names are resolved to - IP addresses. Note that the resolution of a domain-name value - may require to query multiple DNS records (e.g., A for IPv4 - and AAAA for IPv6). The order of the resolution process and - which DNS record takes precedence can either be defined - explicitly or may depend on the configuration of the - resolver. - - Domain-name values use the US-ASCII encoding. Their canonical - format uses lowercase US-ASCII characters. Internationalized - domain names MUST be A-labels as per RFC 5890."; - reference - "RFC 952: DoD Internet Host Table Specification - RFC 1034: Domain Names - Concepts and Facilities - RFC 1123: Requirements for Internet Hosts -- Application - and Support - RFC 2782: A DNS RR for specifying the location of services - (DNS SRV) - RFC 5890: Internationalized Domain Names in Applications - (IDNA): Definitions and Document Framework"; - } - - typedef host { - type union { - type inet:ip-address; - type inet:domain-name; - } - description - "The host type represents either an IP address or a DNS - domain name."; - } - - typedef uri { - type string; - description - "The uri type represents a Uniform Resource Identifier - (URI) as defined by STD 66. - - Objects using the uri type MUST be in US-ASCII encoding, - and MUST be normalized as described by RFC 3986 Sections - 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary - percent-encoding is removed, and all case-insensitive - characters are set to lowercase except for hexadecimal - digits, which are normalized to uppercase as described in - Section 6.2.2.1. - - The purpose of this normalization is to help provide - unique URIs. Note that this normalization is not - sufficient to provide uniqueness. Two URIs that are - textually distinct after this normalization may still be - equivalent. - - Objects using the uri type may restrict the schemes that - they permit. For example, 'data:' and 'urn:' schemes - might not be appropriate. - - A zero-length URI is not a valid URI. This can be used to - express 'URI absent' where required. - - In the value set and its semantics, this type is equivalent - to the Uri SMIv2 textual convention defined in RFC 5017."; - reference - "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax - RFC 3305: Report from the Joint W3C/IETF URI Planning Interest - Group: Uniform Resource Identifiers (URIs), URLs, - and Uniform Resource Names (URNs): Clarifications - and Recommendations - RFC 5017: MIB Textual Conventions for Uniform Resource - Identifiers (URIs)"; - } - - } diff --git a/yang/mandatory/ietf-inet-types@2020-07-06.yang b/yang/mandatory/ietf-inet-types@2020-07-06.yang new file mode 100644 index 00000000..ac33da36 --- /dev/null +++ b/yang/mandatory/ietf-inet-types@2020-07-06.yang @@ -0,0 +1,589 @@ +module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF Network Modeling (NETMOD) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + 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) 2020 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + 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 Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; + see the RFC itself for full legal notices."; + revision 2020-07-06 { + description + "This revision adds the following new data types: + - ip-address-and-prefix + - ipv4-address-and-prefix + - ipv6-address-and-prefix + - email-address"; + reference + "RFC XXXX: Common YANG Data Types"; + } + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or + Flow Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is known + from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is known + from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix. + + The definition of ipv4-prefix does not require that bits, + which are not part of the prefix, are set to zero. However, + implementations have to return values in canonical format, + which requires non-prefix bits to be set to zero. This means + that 192.0.2.1/24 must be accepted as a valid value but it + will be converted into the canonical format 192.0.2.0/24."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + description + "The ipv6-prefix type represents an IPv6 prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952. + + The definition of ipv6-prefix does not require that bits, + which are not part of the prefix, are set to zero. However, + implementations have to return values in canonical format, + which requires non-prefix bits to be set to zero. This means + that 2001:db8::1/64 must be accepted as a valid value but it + will be converted into the canonical format 2001:db8::/64."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-and-prefix { + type union { + type inet:ipv4-address-and-prefix; + type inet:ipv6-address-and-prefix; + } + description + "The ip-address-and-prefix type represents an IP address and + prefix and is IP version neutral. The format of the textual + representations implies the IP version."; + } + + typedef ipv4-address-and-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-address-and-prefix type represents an IPv4 + address and an associated ipv4 prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0."; + } + + typedef ipv6-address-and-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + description + "The ipv6-address-and-prefix type represents an IPv6 + address and an associated ipv4 prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format requires that the IPv6 address is + represented as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + length "1..253"; + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. This + type does not support wildcards (see RFC 4592) or + classless in-addr.arpa delegations (see RFC 2317). + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. Note that Internet host names have a + stricter syntax (described in RFC 952) than the DNS + recommendations in RFCs 1034 and 1123, and that systems + that want to store host names in schema node instances + using the domain-name type are recommended to adhere to + this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2317: Classless IN-ADDR.ARPA delegation + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 4592: The Role of Wildcards in the Domain Name System + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + /* + * DISCUSS: + * - Lada suggested to replace the inet:domain-name usage in + * the union with a new host-name definition that follows + * the NR-LDH definition in RFC 5890. + */ + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + + typedef email-address { + type string { + // dot-atom-text "@" ... + pattern '[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+' + + '(\.[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+)*' + + '@' + + '[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+' + + '(\.[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+)*'; + } + description + "The email-address type represents an email address as + defined as addr-spec in RFC 5322 section 3.4.1."; + reference + "RFC 5322: Internet Message Format"; + } + + /* + * DISCUSS: + * - It was suggested to add email types following RFC 5322 + * email-address (addr-spec, per Section 3.4.1) + * named-email-address (name-addr, per Section 3.4) + * - This sounds useful but the devil is in the details, + * in particular name-addr is a quite complex construct; + * perhaps addr-spec is sufficient, this is also the + * format allowed in mailto: URIs (mailto: seems to use + * only a subset of addr-spec which may be good enough + * here as well). + * - Need to define a pattern that has a meaningful trade-off + * between precision and complexity (there are very tight + * pattern that are very long and complex). The current + * pattern does not take care of quoted-string, obs-local-part, + * domain-literal, obs-domain. + */ + + /* + * DISCUSS: + * - There was a request to add types for URI fields (scheme, + * authority, path, query, fragment) but it is not clear how + * commonly useful these types are, the WG was pretty silent + * about this proposal. On the technical side, it is unclear + * whether data is represented with percent escapes resolved + * or not. (Mahesh's proposal does not spell this out, the + * pattern does not allow the % character, which may be wrong.) + */ +} diff --git a/yang/mandatory/ietf-yang-library@2016-06-21.yang b/yang/mandatory/ietf-yang-library@2016-06-21.yang deleted file mode 100644 index 1e897180..00000000 --- a/yang/mandatory/ietf-yang-library@2016-06-21.yang +++ /dev/null @@ -1,242 +0,0 @@ -module ietf-yang-library { - namespace "urn:ietf:params:xml:ns:yang:ietf-yang-library"; - prefix "yanglib"; - - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { - prefix inet; - } - organization - "IETF NETCONF (Network Configuration) Working Group"; - - contact - "WG Web: - WG List: - - WG Chair: Mehmet Ersue - - - WG Chair: Mahesh Jethanandani - - - Editor: Andy Bierman - - - Editor: Martin Bjorklund - - - Editor: Kent Watsen - "; - - description - "This module contains monitoring information about the YANG - modules and submodules that are used within a YANG-based - server. - - Copyright (c) 2016 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - 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 Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 7895; see - the RFC itself for full legal notices."; - - revision 2016-06-21 { - description - "Initial revision."; - reference - "RFC 7895: YANG Module Library."; - } - - /* - * Typedefs - */ - - typedef revision-identifier { - type string { - pattern '\d{4}-\d{2}-\d{2}'; - } - description - "Represents a specific date in YYYY-MM-DD format."; - } - - /* - * Groupings - */ - - grouping module-list { - description - "The module data structure is represented as a grouping - so it can be reused in configuration or another monitoring - data structure."; - - grouping common-leafs { - description - "Common parameters for YANG modules and submodules."; - - leaf name { - type yang:yang-identifier; - description - "The YANG module or submodule name."; - } - leaf revision { - type union { - type revision-identifier; - type string { length 0; } - } - description - "The YANG module or submodule revision date. - A zero-length string is used if no revision statement - is present in the YANG module or submodule."; - } - } - - grouping schema-leaf { - description - "Common schema leaf parameter for modules and submodules."; - leaf schema { - type inet:uri; - description - "Contains a URL that represents the YANG schema - resource for this module or submodule. - - This leaf will only be present if there is a URL - available for retrieval of the schema for this entry."; - } - } - - list module { - key "name revision"; - description - "Each entry represents one revision of one module - currently supported by the server."; - - uses common-leafs; - uses schema-leaf; - - leaf namespace { - type inet:uri; - mandatory true; - description - "The XML namespace identifier for this module."; - } - leaf-list feature { - type yang:yang-identifier; - description - "List of YANG feature names from this module that are - supported by the server, regardless of whether they are - defined in the module or any included submodule."; - } - list deviation { - key "name revision"; - description - "List of YANG deviation module names and revisions - used by this server to modify the conformance of - the module associated with this entry. Note that - the same module can be used for deviations for - multiple modules, so the same entry MAY appear - within multiple 'module' entries. - - The deviation module MUST be present in the 'module' - list, with the same name and revision values. - The 'conformance-type' value will be 'implement' for - the deviation module."; - uses common-leafs; - } - leaf conformance-type { - type enumeration { - enum implement { - description - "Indicates that the server implements one or more - protocol-accessible objects defined in the YANG module - identified in this entry. This includes deviation - statements defined in the module. - - For YANG version 1.1 modules, there is at most one - module entry with conformance type 'implement' for a - particular module name, since YANG 1.1 requires that, - at most, one revision of a module is implemented. - - For YANG version 1 modules, there SHOULD NOT be more - than one module entry for a particular module name."; - } - enum import { - description - "Indicates that the server imports reusable definitions - from the specified revision of the module but does - not implement any protocol-accessible objects from - this revision. - - Multiple module entries for the same module name MAY - exist. This can occur if multiple modules import the - same module but specify different revision dates in - the import statements."; - } - } - mandatory true; - description - "Indicates the type of conformance the server is claiming - for the YANG module identified by this entry."; - } - list submodule { - key "name revision"; - description - "Each entry represents one submodule within the - parent module."; - uses common-leafs; - uses schema-leaf; - } - } - } - - - - /* - * Operational state data nodes - */ - - container modules-state { - config false; - description - "Contains YANG module monitoring information."; - - leaf module-set-id { - type string; - mandatory true; - description - "Contains a server-specific identifier representing - the current set of modules and submodules. The - server MUST change the value of this leaf if the - information represented by the 'module' list instances - has changed."; - } - - uses module-list; - } - - /* - * Notifications - */ - notification yang-library-change { - description - "Generated when the set of modules and submodules supported - by the server has changed."; - leaf module-set-id { - type leafref { - path "/yanglib:modules-state/yanglib:module-set-id"; - } - mandatory true; - description - "Contains the module-set-id value representing the - set of modules and submodules supported at the server at - the time the notification is generated."; - } - } -} \ No newline at end of file diff --git a/yang/mandatory/ietf-yang-library@2019-01-04.yang b/yang/mandatory/ietf-yang-library@2019-01-04.yang new file mode 100644 index 00000000..dac53a1d --- /dev/null +++ b/yang/mandatory/ietf-yang-library@2019-01-04.yang @@ -0,0 +1,544 @@ +module ietf-yang-library { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-library"; + prefix yanglib; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-datastores { + prefix ds; + reference + "RFC 8342: Network Management Datastore Architecture + (NMDA)"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + + + Author: Juergen Schoenwaelder + + + Author: Kent Watsen + + + Author: Robert Wilton + "; + description + "This module provides information about the YANG modules, + datastores, and datastore schemas used by a network + management server. + 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) 2019 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + 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 Simplified 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 8525; see + the RFC itself for full legal notices."; + + revision 2019-01-04 { + description + "Added support for multiple datastores according to the + Network Management Datastore Architecture (NMDA)."; + reference + "RFC 8525: YANG Library"; + } + revision 2016-04-09 { + description + "Initial revision."; + reference + "RFC 7895: YANG Module Library"; + } + + /* + * Typedefs + */ + + typedef revision-identifier { + type string { + pattern '\d{4}-\d{2}-\d{2}'; + } + description + "Represents a specific date in YYYY-MM-DD format."; + } + + /* + * Groupings + */ + grouping module-identification-leafs { + description + "Parameters for identifying YANG modules and submodules."; + leaf name { + type yang:yang-identifier; + mandatory true; + description + "The YANG module or submodule name."; + } + leaf revision { + type revision-identifier; + description + "The YANG module or submodule revision date. If no revision + statement is present in the YANG module or submodule, this + leaf is not instantiated."; + } + } + + grouping location-leaf-list { + description + "Common leaf-list parameter for the locations of modules and + submodules."; + leaf-list location { + type inet:uri; + description + "Contains a URL that represents the YANG schema + resource for this module or submodule. + + This leaf will only be present if there is a URL + available for retrieval of the schema for this entry."; + } + } + + grouping module-implementation-parameters { + description + "Parameters for describing the implementation of a module."; + leaf-list feature { + type yang:yang-identifier; + description + "List of all YANG feature names from this module that are + supported by the server, regardless whether they are defined + in the module or any included submodule."; + } + leaf-list deviation { + type leafref { + path "../../module/name"; + } + + description + "List of all YANG deviation modules used by this server to + modify the conformance of the module associated with this + entry. Note that the same module can be used for deviations + for multiple modules, so the same entry MAY appear within + multiple 'module' entries. + + This reference MUST NOT (directly or indirectly) + refer to the module being deviated. + + Robust clients may want to make sure that they handle a + situation where a module deviates itself (directly or + indirectly) gracefully."; + } + } + + grouping module-set-parameters { + description + "A set of parameters that describe a module set."; + leaf name { + type string; + description + "An arbitrary name of the module set."; + } + list module { + key "name"; + description + "An entry in this list represents a module implemented by the + server, as per Section 5.6.5 of RFC 7950, with a particular + set of supported features and deviations."; + reference + "RFC 7950: The YANG 1.1 Data Modeling Language"; + uses module-identification-leafs; + leaf namespace { + type inet:uri; + mandatory true; + description + "The XML namespace identifier for this module."; + } + uses location-leaf-list; + list submodule { + key "name"; + description + "Each entry represents one submodule within the + parent module."; + uses module-identification-leafs; + uses location-leaf-list; + } + uses module-implementation-parameters; + } + list import-only-module { + key "name revision"; + description + "An entry in this list indicates that the server imports + reusable definitions from the specified revision of the + module but does not implement any protocol-accessible + objects from this revision. + + Multiple entries for the same module name MAY exist. This + can occur if multiple modules import the same module but + specify different revision dates in the import statements."; + leaf name { + type yang:yang-identifier; + description + "The YANG module name."; + } + leaf revision { + type union { + type revision-identifier; + type string { + length "0"; + } + } + description + "The YANG module revision date. + A zero-length string is used if no revision statement + is present in the YANG module."; + } + leaf namespace { + type inet:uri; + mandatory true; + description + "The XML namespace identifier for this module."; + } + uses location-leaf-list; + list submodule { + key "name"; + description + "Each entry represents one submodule within the + parent module."; + uses module-identification-leafs; + uses location-leaf-list; + } + } + } + + grouping yang-library-parameters { + description + "The YANG library data structure is represented as a grouping + so it can be reused in configuration or another monitoring + data structure."; + list module-set { + key "name"; + description + "A set of modules that may be used by one or more schemas. + + A module set does not have to be referentially complete, + i.e., it may define modules that contain import statements + for other modules not included in the module set."; + uses module-set-parameters; + } + list schema { + key "name"; + description + "A datastore schema that may be used by one or more + datastores. + + The schema must be valid and referentially complete, i.e., + it must contain modules to satisfy all used import + statements for all modules specified in the schema."; + leaf name { + type string; + description + "An arbitrary name of the schema."; + } + leaf-list module-set { + type leafref { + path "../../module-set/name"; + } + description + "A set of module-sets that are included in this schema. + If a non-import-only module appears in multiple module + sets, then the module revision and the associated features + and deviations must be identical."; + } + } + list datastore { + key "name"; + description + "A datastore supported by this server. + + Each datastore indicates which schema it supports. + + The server MUST instantiate one entry in this list per + specific datastore it supports. + Each datastore entry with the same datastore schema SHOULD + reference the same schema."; + leaf name { + type ds:datastore-ref; + description + "The identity of the datastore."; + } + leaf schema { + type leafref { + path "../../schema/name"; + } + mandatory true; + description + "A reference to the schema supported by this datastore. + All non-import-only modules of the schema are implemented + with their associated features and deviations."; + } + } + } + + /* + * Top-level container + */ + + container yang-library { + config false; + description + "Container holding the entire YANG library of this server."; + uses yang-library-parameters; + leaf content-id { + type string; + mandatory true; + description + "A server-generated identifier of the contents of the + '/yang-library' tree. The server MUST change the value of + this leaf if the information represented by the + '/yang-library' tree, except '/yang-library/content-id', has + changed."; + } + } + + /* + * Notifications + */ + + notification yang-library-update { + description + "Generated when any YANG library information on the + server has changed."; + leaf content-id { + type leafref { + path "/yanglib:yang-library/yanglib:content-id"; + } + mandatory true; + description + "Contains the YANG library content identifier for the updated + YANG library at the time the notification is generated."; + } + } + + /* + * Legacy groupings + */ + + grouping module-list { + status deprecated; + description + "The module data structure is represented as a grouping + so it can be reused in configuration or another monitoring + data structure."; + + grouping common-leafs { + status deprecated; + description + "Common parameters for YANG modules and submodules."; + leaf name { + type yang:yang-identifier; + status deprecated; + description + "The YANG module or submodule name."; + } + leaf revision { + type union { + type revision-identifier; + type string { + length "0"; + } + } + status deprecated; + description + "The YANG module or submodule revision date. + A zero-length string is used if no revision statement + is present in the YANG module or submodule."; + } + } + + grouping schema-leaf { + status deprecated; + description + "Common schema leaf parameter for modules and submodules."; + leaf schema { + type inet:uri; + description + "Contains a URL that represents the YANG schema + resource for this module or submodule. + + This leaf will only be present if there is a URL + available for retrieval of the schema for this entry."; + } + } + list module { + key "name revision"; + status deprecated; + description + "Each entry represents one revision of one module + currently supported by the server."; + uses common-leafs { + status deprecated; + } + uses schema-leaf { + status deprecated; + } + leaf namespace { + type inet:uri; + mandatory true; + status deprecated; + description + "The XML namespace identifier for this module."; + } + leaf-list feature { + type yang:yang-identifier; + status deprecated; + description + "List of YANG feature names from this module that are + supported by the server, regardless of whether they are + defined in the module or any included submodule."; + } + list deviation { + key "name revision"; + status deprecated; + + description + "List of YANG deviation module names and revisions + used by this server to modify the conformance of + the module associated with this entry. Note that + the same module can be used for deviations for + multiple modules, so the same entry MAY appear + within multiple 'module' entries. + + The deviation module MUST be present in the 'module' + list, with the same name and revision values. + The 'conformance-type' value will be 'implement' for + the deviation module."; + uses common-leafs { + status deprecated; + } + } + leaf conformance-type { + type enumeration { + enum implement { + description + "Indicates that the server implements one or more + protocol-accessible objects defined in the YANG module + identified in this entry. This includes deviation + statements defined in the module. + + For YANG version 1.1 modules, there is at most one + 'module' entry with conformance type 'implement' for a + particular module name, since YANG 1.1 requires that + at most one revision of a module is implemented. + + For YANG version 1 modules, there SHOULD NOT be more + than one 'module' entry for a particular module + name."; + } + enum import { + description + "Indicates that the server imports reusable definitions + from the specified revision of the module but does + not implement any protocol-accessible objects from + this revision. + + Multiple 'module' entries for the same module name MAY + exist. This can occur if multiple modules import the + same module but specify different revision dates in + the import statements."; + } + } + mandatory true; + status deprecated; + description + "Indicates the type of conformance the server is claiming + for the YANG module identified by this entry."; + } + list submodule { + key "name revision"; + status deprecated; + description + "Each entry represents one submodule within the + parent module."; + uses common-leafs { + status deprecated; + } + uses schema-leaf { + status deprecated; + } + } + } + } + + /* + * Legacy operational state data nodes + */ + + container modules-state { + config false; + status deprecated; + description + "Contains YANG module monitoring information."; + leaf module-set-id { + type string; + mandatory true; + status deprecated; + description + "Contains a server-specific identifier representing + the current set of modules and submodules. The + server MUST change the value of this leaf if the + information represented by the 'module' list instances + has changed."; + } + uses module-list { + status deprecated; + } + } + + /* + * Legacy notifications + */ + + notification yang-library-change { + status deprecated; + description + "Generated when the set of modules and submodules supported + by the server has changed."; + leaf module-set-id { + type leafref { + path "/yanglib:modules-state/yanglib:module-set-id"; + } + mandatory true; + status deprecated; + description + "Contains the module-set-id value representing the + set of modules and submodules supported at the server + at the time the notification is generated."; + } + } +} From cd45f277ef42331a39bcfdb122310abfeeed8644 Mon Sep 17 00:00:00 2001 From: Jonathan Ben-Avraham Date: Sat, 7 Nov 2020 22:11:35 +0200 Subject: [PATCH 3/4] Added basic rfc8527 support Added basic rfc8527 support, but without support for: * ds:operational * with-origin * clixon/test/test_rfc8527_*.sh The current level of rfc8527 support is intended to allow commit operations on the 'candidate' datastore without rewriting the 'startup' datastore. --- apps/restconf/restconf_lib.h | 12 +++ apps/restconf/restconf_methods.c | 38 +++++---- apps/restconf/restconf_methods.h | 6 +- apps/restconf/restconf_methods_get.c | 6 +- apps/restconf/restconf_methods_get.h | 4 +- apps/restconf/restconf_methods_post.c | 13 +-- apps/restconf/restconf_methods_post.h | 2 +- apps/restconf/restconf_root.c | 117 ++++++++++++++++++++++---- apps/restconf/restconf_root.h | 1 + 9 files changed, 152 insertions(+), 47 deletions(-) diff --git a/apps/restconf/restconf_lib.h b/apps/restconf/restconf_lib.h index 3c0d9569..0ce99064 100644 --- a/apps/restconf/restconf_lib.h +++ b/apps/restconf/restconf_lib.h @@ -56,6 +56,18 @@ enum restconf_media{ }; typedef enum restconf_media restconf_media; +/* @See https://tools.ietf.org/html/rfc8342, ietf-datastores@2018-02-14.yang */ +enum ietf_ds { + IETF_DS_NONE = 0, + IETF_DS_RUNNING, + IETF_DS_CANDIDATE, + IETF_DS_STARTUP, + IETF_DS_INTENDED, + IETF_DS_DYNAMIC, + IETF_DS_OPERATIONAL +}; +typedef enum ietf_ds ietf_ds_t; + /* * Prototypes */ diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index d2f38022..1fb6060f 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -230,6 +230,7 @@ match_list_keys(yang_stmt *y, * PUT: If it does not, set op to create, otherwise replace * PATCH: If it does not, fail, otherwise replace/merge * @param[in] plain_patch fail if object does not exists AND merge (not replace) + * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource */ static int api_data_write(clicon_handle h, @@ -242,7 +243,8 @@ api_data_write(clicon_handle h, int pretty, restconf_media media_in, restconf_media media_out, - int plain_patch) + int plain_patch, + ietf_ds_t ds) { int retval = -1; enum operation_type op; @@ -596,12 +598,12 @@ api_data_write(clicon_handle h, NETCONF_BASE_NAMESPACE); /* bind nc to netconf namespace */ cprintf(cbx, ""); @@ -695,13 +697,14 @@ api_data_put(clicon_handle h, cvec *qvec, char *data, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { restconf_media media_in; media_in = restconf_content_type(h); return api_data_write(h, req, api_path0, pcvec, pi, qvec, data, pretty, - media_in, media_out, 0); + media_in, media_out, 0, ds); } /*! Generic REST PATCH method for plain patch @@ -730,7 +733,8 @@ api_data_patch(clicon_handle h, cvec *qvec, char *data, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { restconf_media media_in; int ret; @@ -740,7 +744,7 @@ api_data_patch(clicon_handle h, case YANG_DATA_XML: case YANG_DATA_JSON: /* plain patch */ ret = api_data_write(h, req, api_path0, pcvec, pi, qvec, data, pretty, - media_in, media_out, 1); + media_in, media_out, 1, ds); break; case YANG_PATCH_XML: case YANG_PATCH_JSON: /* RFC 8072 patch */ @@ -760,6 +764,7 @@ api_data_patch(clicon_handle h, * @param[in] pi Offset, where path starts * @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] media_out Output media + * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * See RFC 8040 Sec 4.7 * Example: * curl -X DELETE http://127.0.0.1/restconf/data/interfaces/interface=eth0 @@ -771,7 +776,8 @@ api_data_delete(clicon_handle h, char *api_path, int pi, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { int retval = -1; int i; @@ -834,12 +840,12 @@ api_data_delete(clicon_handle h, cprintf(cbx, ""); diff --git a/apps/restconf/restconf_methods.h b/apps/restconf/restconf_methods.h index 4a665470..81d91345 100644 --- a/apps/restconf/restconf_methods.h +++ b/apps/restconf/restconf_methods.h @@ -46,14 +46,14 @@ int api_data_options(clicon_handle h, void *req); int api_data_put(clicon_handle h, void *req, char *api_path, cvec *pcvec, int pi, cvec *qvec, char *data, - int pretty, restconf_media media_out); + int pretty, restconf_media media_out, ietf_ds_t ds); int api_data_patch(clicon_handle h, void *req, char *api_path, cvec *pcvec, int pi, cvec *qvec, char *data, int pretty, - restconf_media media_out); + restconf_media media_out, ietf_ds_t ds); int api_data_delete(clicon_handle h, void *req, char *api_path, int pi, - int pretty, restconf_media media_out); + int pretty, restconf_media media_out, ietf_ds_t ds); #endif /* _RESTCONF_METHODS_H_ */ diff --git a/apps/restconf/restconf_methods_get.c b/apps/restconf/restconf_methods_get.c index 3fccdf74..2effa090 100644 --- a/apps/restconf/restconf_methods_get.c +++ b/apps/restconf/restconf_methods_get.c @@ -363,7 +363,8 @@ api_data_head(clicon_handle h, int pi, cvec *qvec, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { return api_data_get2(h, req, api_path, pcvec, pi, qvec, pretty, media_out, 1); } @@ -402,7 +403,8 @@ api_data_get(clicon_handle h, int pi, cvec *qvec, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { return api_data_get2(h, req, api_path, pcvec, pi, qvec, pretty, media_out, 0); } diff --git a/apps/restconf/restconf_methods_get.h b/apps/restconf/restconf_methods_get.h index 56d758f5..34e4244e 100644 --- a/apps/restconf/restconf_methods_get.h +++ b/apps/restconf/restconf_methods_get.h @@ -42,9 +42,9 @@ * Prototypes */ int api_data_head(clicon_handle h, void *req, char *api_path, cvec *pcvec, int pi, - cvec *qvec, int pretty, restconf_media media_out); + cvec *qvec, int pretty, restconf_media media_out, ietf_ds_t ds); int api_data_get(clicon_handle h, void *req, char *api_path, cvec *pcvec, int pi, - cvec *qvec, int pretty, restconf_media media_out); + cvec *qvec, int pretty, restconf_media media_out, ietf_ds_t ds); int api_operations_get(clicon_handle h, void *req, char *api_path, int pi, cvec *qvec, char *data, int pretty, restconf_media media_out); diff --git a/apps/restconf/restconf_methods_post.c b/apps/restconf/restconf_methods_post.c index b51a9262..369c7c26 100644 --- a/apps/restconf/restconf_methods_post.c +++ b/apps/restconf/restconf_methods_post.c @@ -152,7 +152,8 @@ api_data_post(clicon_handle h, cvec *qvec, char *data, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { int retval = -1; enum operation_type op = OP_CREATE; @@ -377,12 +378,12 @@ api_data_post(clicon_handle h, cprintf(cbx, ""); diff --git a/apps/restconf/restconf_methods_post.h b/apps/restconf/restconf_methods_post.h index b8d8bd83..52fab3c8 100644 --- a/apps/restconf/restconf_methods_post.h +++ b/apps/restconf/restconf_methods_post.h @@ -44,7 +44,7 @@ int api_data_post(clicon_handle h, void *req, char *api_path, int pi, cvec *qvec, char *data, int pretty, - restconf_media media_out); + restconf_media media_out, ietf_ds_t ds); int api_operations_post(clicon_handle h, void *req, char *api_path, int pi, cvec *qvec, char *data, diff --git a/apps/restconf/restconf_root.c b/apps/restconf/restconf_root.c index 8872e642..7a4630fc 100644 --- a/apps/restconf/restconf_root.c +++ b/apps/restconf/restconf_root.c @@ -153,7 +153,8 @@ api_root_restconf_exact(clicon_handle h, goto done; if (clixon_xml_parse_string("" - "2016-06-21", + "" IETF_YANG_LIBRARY_REVISION + "", YB_MODULE, yspec, &xt, NULL) < 0) goto done; @@ -187,6 +188,24 @@ api_root_restconf_exact(clicon_handle h, return retval; } +/** A stub implementation of the operational state datastore. The full + * implementation is required by https://tools.ietf.org/html/rfc8527#section-3.1 + */ +static int +api_operational_state(clicon_handle h, + void *req, + char *request_method, + int pretty, + restconf_media media_out) + +{ + clicon_debug(1, "%s request method:%s", __FUNCTION__, request_method); + + /* We are not implementing this method at this time, 20201105 despite it + * being mandatory https://tools.ietf.org/html/rfc8527#section-3.1 */ + return restconf_notimplemented(req); +} + /*! * See https://tools.ietf.org/html/rfc7895 */ @@ -200,7 +219,6 @@ api_yang_library_version(clicon_handle h, int retval = -1; cxobj *xt = NULL; cbuf *cb = NULL; - char *ietf_yang_library_revision = "2016-06-21"; /* XXX */ clicon_debug(1, "%s", __FUNCTION__); if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0) @@ -209,7 +227,7 @@ api_yang_library_version(clicon_handle h, goto done; if (clixon_xml_parse_va(YB_NONE, NULL, &xt, NULL, "%s", - ietf_yang_library_revision) < 0) + IETF_YANG_LIBRARY_REVISION) < 0) goto done; if (xml_rootchild(xt, 0, &xt) < 0) goto done; @@ -250,6 +268,7 @@ api_yang_library_version(clicon_handle h, * @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] media_in Input media * @param[in] media_out Output media + * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource */ static int api_data(clicon_handle h, @@ -260,28 +279,58 @@ api_data(clicon_handle h, cvec *qvec, char *data, int pretty, - restconf_media media_out) + restconf_media media_out, + ietf_ds_t ds) { int retval = -1; + int read_only = 0, dynamic = 0; char *request_method; clicon_debug(1, "%s", __FUNCTION__); request_method = restconf_param_get(h, "REQUEST_METHOD"); clicon_debug(1, "%s method:%s", __FUNCTION__, request_method); + + /* https://tools.ietf.org/html/rfc8527#section-3.2 */ + /* We assume that dynamic datastores are read only at this time 20201105 */ + if (IETF_DS_DYNAMIC == ds) + dynamic = 1; + if ((IETF_DS_INTENDED == ds) || (IETF_DS_RUNNING == ds) + || (IETF_DS_DYNAMIC == ds) || (IETF_DS_OPERATIONAL == ds)) { + read_only = 1; + } + if (strcmp(request_method, "OPTIONS")==0) retval = api_data_options(h, req); - else if (strcmp(request_method, "HEAD")==0) - retval = api_data_head(h, req, api_path, pcvec, pi, qvec, pretty, media_out); - else if (strcmp(request_method, "GET")==0) - retval = api_data_get(h, req, api_path, pcvec, pi, qvec, pretty, media_out); - else if (strcmp(request_method, "POST")==0) - retval = api_data_post(h, req, api_path, pi, qvec, data, pretty, media_out); - else if (strcmp(request_method, "PUT")==0) - retval = api_data_put(h, req, api_path, pcvec, pi, qvec, data, pretty, media_out); - else if (strcmp(request_method, "PATCH")==0) - retval = api_data_patch(h, req, api_path, pcvec, pi, qvec, data, pretty, media_out); - else if (strcmp(request_method, "DELETE")==0) - retval = api_data_delete(h, req, api_path, pi, pretty, media_out); + else if (strcmp(request_method, "HEAD")==0) { + if (dynamic) { + retval = restconf_method_notallowed(req, "GET,POST"); + } + retval = api_data_head(h, req, api_path, pcvec, pi, qvec, pretty, media_out, ds); + } + else if (strcmp(request_method, "GET")==0) { + retval = api_data_get(h, req, api_path, pcvec, pi, qvec, pretty, media_out, ds); + } + else if (strcmp(request_method, "POST")==0) { + retval = api_data_post(h, req, api_path, pi, qvec, data, pretty, media_out, ds); + } + else if (strcmp(request_method, "PUT")==0) { + if (read_only) { + retval = restconf_method_notallowed(req, "GET,POST"); + } + retval = api_data_put(h, req, api_path, pcvec, pi, qvec, data, pretty, media_out, ds); + } + else if (strcmp(request_method, "PATCH")==0) { + if (read_only) { + retval = restconf_method_notallowed(req, "GET,POST"); + } + retval = api_data_patch(h, req, api_path, pcvec, pi, qvec, data, pretty, media_out, ds); + } + else if (strcmp(request_method, "DELETE")==0) { + if (read_only) { + retval = restconf_method_notallowed(req, "GET,POST"); + } + retval = api_data_delete(h, req, api_path, pi, pretty, media_out, ds); + } else retval = restconf_notfound(h, req); clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); @@ -441,7 +490,41 @@ api_root_restconf(clicon_handle h, } else if (strcmp(api_resource, "data") == 0){ /* restconf, skip /api/data */ if (api_data(h, req, path, pcvec, 2, qvec, indata, - pretty, media_out) < 0) + pretty, media_out, IETF_DS_NONE) < 0) + goto done; + } + else if (strcmp(api_resource, "ds") == 0) { + /* We should really be getting the supported datastore types from the + * application model, but at this time the datastore model of startup/ + * running/cadidate is hardcoded into the clixon implementation. 20201104 */ + ietf_ds_t ds = IETF_DS_NONE; + + if (4 > pn) { /* Malformed request, no "ietf-datastores:" component */ + restconf_notfound(h, req); + goto done; + } + + /* Assign ds; See https://tools.ietf.org/html/rfc8342#section-7 */ + if (0 == strcmp(pvec[3], "ietf-datastores:running")) + ds = IETF_DS_RUNNING; + else if (0 == strcmp(pvec[3], "ietf-datastores:candidate")) + ds = IETF_DS_CANDIDATE; + else if (0 == strcmp(pvec[3], "ietf-datastores:startup")) + ds = IETF_DS_STARTUP; + else if (0 == strcmp(pvec[3], "ietf-datastores:operational")) { + /* See https://tools.ietf.org/html/rfc8527#section-3.1 + * https://tools.ietf.org/html/rfc8342#section-5.3 */ + if (0 > api_operational_state(h, req, request_method, pretty, media_out)) { + goto done; + } + goto ok; + } + else { /* Malformed request, unsupported datastore type */ + restconf_notfound(h, req); + goto done; + } + /* ds is assigned at this point */ + if (0 > api_data(h, req, path, pcvec, 3, qvec, indata, pretty, media_out, ds)) goto done; } else if (strcmp(api_resource, "operations") == 0){ /* rpc */ diff --git a/apps/restconf/restconf_root.h b/apps/restconf/restconf_root.h index 10010483..2a60c133 100644 --- a/apps/restconf/restconf_root.h +++ b/apps/restconf/restconf_root.h @@ -42,6 +42,7 @@ * Constants */ #define RESTCONF_API "restconf" +#define IETF_YANG_LIBRARY_REVISION "2019-01-04" /* RESTCONF enables deployments to specify where the RESTCONF API is located. The client discovers this by getting the "/.well-known/host-meta" From 0f1a2ef6318217caae39fe89c6dd1dbdef0453c4 Mon Sep 17 00:00:00 2001 From: Jonathan Ben-Avraham Date: Wed, 11 Nov 2020 13:54:09 +0200 Subject: [PATCH 4/4] Whitespace fix --- apps/restconf/restconf_root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/restconf/restconf_root.c b/apps/restconf/restconf_root.c index 7a4630fc..e1854965 100644 --- a/apps/restconf/restconf_root.c +++ b/apps/restconf/restconf_root.c @@ -505,7 +505,7 @@ api_root_restconf(clicon_handle h, } /* Assign ds; See https://tools.ietf.org/html/rfc8342#section-7 */ - if (0 == strcmp(pvec[3], "ietf-datastores:running")) + if (0 == strcmp(pvec[3], "ietf-datastores:running")) ds = IETF_DS_RUNNING; else if (0 == strcmp(pvec[3], "ietf-datastores:candidate")) ds = IETF_DS_CANDIDATE;