<?xml version="1.0" encoding="US-ASCII"?>
<!-- This is built from a template for a generic Internet Draft. Suggestions for
     improvement welcome - write to Brian Carpenter, brian.e.carpenter @ gmail.com 
     This can be converted using the Web service at http://xml.resource.org/ -->
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
<?rfc toc="yes"?>
<!-- You want a table of contents -->
<?rfc symrefs="yes"?>
<!-- Use symbolic labels for references -->
<?rfc sortrefs="yes"?>
<!-- This sorts the references -->
<?rfc iprnotified="no" ?>
<!-- Change to "yes" if someone has disclosed IPR for the draft -->
<?rfc compact="yes"?>
<!-- This defines the specific filename and version number of your draft (and inserts the appropriate IETF boilerplate -->
<rfc category="std" docName="draft-liu-anima-grasp-api-01" ipr="trust200902">
  <front>
    <title abbrev="GRASP API">Generic Autonomic Signaling Protocol Application
    Program Interface (GRASP API)</title>

    <author fullname="Brian Carpenter" initials="B. E." surname="Carpenter">
      <organization abbrev="Univ. of Auckland"/>

      <address>
        <postal>
          <street>Department of Computer Science</street>
          <street>University of Auckland</street>
          <street>PB 92019</street>
          <city>Auckland</city>
          <region/>
          <code>1142</code>
          <country>New Zealand</country>
        </postal>

        <email>brian.e.carpenter@gmail.com</email>
      </address>
    </author>

    <author fullname="Bing Liu" initials="B." role="editor" surname="Liu">
      <organization>Huawei Technologies</organization>
      <address>
        <postal>
          <street>Q14, Huawei Campus</street>
          <street>No.156 Beiqing Road</street>
          <city>Hai-Dian District, Beijing</city>
          <code>100095</code>
          <country>P.R. China</country>
        </postal>
        <email>leo.liubing@huawei.com</email>
      </address>
    </author>

    <author fullname="Wendong Wang" initials="W." surname="Wang  ">
      <organization>BUPT University</organization>

      <address>
        <postal>
          <street>Beijing University of Posts &amp; Telecom.</street>
          <street>No.10 Xitucheng Road</street>
          <city>Hai-Dian District, Beijing 100876</city>
          <country>P.R. China</country>
        </postal>
        <email>wdwang@bupt.edu.cn</email>
      </address>
    </author>

    <author fullname="Xiangyang Gong" initials="X." surname="Gong">
      <organization>BUPT University</organization>
      <address>
        <postal>
          <street>Beijing University of Posts &amp; Telecom.</street>
          <street>No.10 Xitucheng Road</street>
          <city>Hai-Dian District, Beijing 100876</city>
          <country>P.R. China</country>
        </postal>
        <email>xygong@bupt.edu.cn</email>
      </address>
    </author>

    <!---->

    <date day="24" month="June" year="2016"/>

    <abstract>
      <t>This document specifies the application programming interface (API) of the
      Generic Autonomic Signaling Protocol (GRASP). The API is used for
      Autonomic Service Agents (ASA) calling the GRASP protocol module to
      communicate autonomic network signalings with other ASAs.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="intro" title="Introduction">
      <t>As defined in <xref target="I-D.ietf-anima-reference-model"/> , the
      Autonomic Serveice Agent (ASA)
      is the atomic entity of an autonomic function; and it is instantiated
      on autonomic nodes. When ASAs communicate with each other, they should
      use the Generic Autonomic Signaling Protocol (GRASP) <xref target="I-D.ietf-anima-grasp"/>.</t>

      <t>As the following figure shows, the GRASP could contain two major
      sub-layers. The bottom is the GRASP base protocol module, which is only
      responsible for sending and recieving GRASP messages. The upper layer is
      some extended functions based upon GRASP basic protocol. For example,
      <xref target="I-D.liu-anima-grasp-distribution"/> is one of the extended
      functions.</t>
      
      <t>It is desirable that ASAs can be designed as portable user-space programs
      using a portable API. In many operating systems, the GRASP module will therefore
      be split into two layers, one being a library that provides the API and the other
      being kernel code containing common components such as multicast handling and
      the discovery cache. The details of this are system-dependent.
      </t>

      <t><figure>
          <artwork align="center"><![CDATA[+----+                              +----+
|ASAs|                              |ASAs|
+----+                              +----+
   |                                   |
   | GRASP Function API                |
   |                                   |
+------------------+                   |GRASP API
| GRASP Extended   |                   |
| Function Modules |                   |
+------------------+                   |
+------------------------------------------+
|                   GRASP Library          |
|  GRASP Module - - - - - - - - - - - - - -|
|                   GRASP Kernel           |
+------------------------------------------+
]]></artwork>
        </figure></t>

      <t>Both the GRASP base module and the extended function modules should
      be available to the ASAs. Thus, there needs to be two sub-sets of API.
      However, since the extended functions are expected to be added in an incremental
      manner, it is inappropriate to define the function APIs in a single
      document. This document only defines the base GRASP API.</t>
    </section>

    <section title="GRASP API for ASA">
      <t/>

      <section title="Design Principles">
        <t>The assumption of this document is that any Autonomic Service Agent
        (ASA) needs to call a GRASP module that handles protocol details
        (security, sending and listening for GRASP messages, waiting, caching
        discovery results, negotiation looping, sending and receiving
        sychronization data, etc.) but understands nothing about individual
        objectives. So this is a high level abstract API for use by ASAs. Individual 
        language bindings should be defined in separate documents.</t>
        
        <t>An assumption of this API is that ASAs may fall into various classes:
        <list style="symbols">
        <t>ASAs that only use GRASP for discovery purposes.</t>
        <t>ASAs that use GRASP negotiation but only as an initiator (client).</t>
        <t>ASAs that use GRASP negotiation but only as a responder.</t>
        <t>ASAs that use GRASP negotiation as an initiator or responder.</t>
        <t>ASAs that use GRASP synchronization but only as an initiator (recipient).</t>
        <t>ASAs that use GRASP synchronization but only as a responder and/or flooder.</t>
        <t>ASAs that use GRASP synchronization as an initiator, responder and/or flooder.</t>
        </list>
        The API also assumes that one ASA may support multiple objectives. Nothing prevents
        an ASA from supporting some objectives for synchronization and others for negotiation.
        </t>

        <t>This is a preliminary version. Two particular gaps exist:<list style="symbols">
            <t>Authorization of ASAs is out of scope.</t>

            <t>The Rapid mode of GRASP is not supported.</t>
          </list></t>
      </section>

      <section title="API definition">
      
      <section title="Parameters and data structures">
      
      <t>Wherever a 'timeout' parameter appears, it is an integer expressed
      in milliseconds. If it is zero, the GRASP default timeout (GRASP_DEF_TIMEOUT,
      see <xref target="I-D.ietf-anima-grasp"/>) will apply. If no response
      is received before the timeout expires, the call will fail unless otherwise noted.</t>
      
      <t>An 'objective' parameter is a data structure with the following components:
        <list style="symbols">
        <t>name (UTF-8 string) - the objective's name</t>
        <t>neg (Boolean) - True if objective supports negotiation (default False)</t>
        <t>synch (Boolean) - True if objective supports synchronization (default False)</t>
        <t>loop_count (integer) - Limit on negotiation steps etc. (default GRASP_DEF_LOOPCT,
        see <xref target="I-D.ietf-anima-grasp"/>)</t>
        <t>value - a specific data structure expressing the value of the objective. The format is 
           language dependent, with the constraint that it can be validly represented in CBOR (default integer = 0).</t>
        </list>
      </t>
      
      <t>An 'ASA_locator' parameter is a data structure with the following contents:
        <list style="symbols">
        <t>locator - The actual locator, either an IP address or an ASCII string.</t>
        <t>ifi (integer) - The interface identifier index via which this was discovered - probably no use to a normal ASA</t>
        <t>expire (system dependent type) - The time on the local system clock when this locator will expire from the cache</t>
        <t>is_ipaddress (Boolean) - True if the locator is an IP address</t>
        <t>is_fqdn (Boolean) - True if the locator is an FQDN</t>
        <t>is_uri (Boolean) - True if the locator is a URI</t>
        <t>diverted (Boolean) - True if the locator was discovered via a Divert option</t>
        <t>protocol (integer) - Applicable transport protocol (IPPROTO_TCP or IPPROTO_UDP)</t>
        <t>port (integer) - Applicable port number</t>
        </list>
      </t>
      
     <t>In most calls, an 'asa_nonce' parameter is required. It is generated when an ASA registers with GRASP,
     and any call in which an invalid nonce is presented will fail.
     It is an up to 24-bit opaque value (for example represented as a uint32_t, depending on the language).
     It should be unpredictable; a possible implementation is to use the same mechanism that GRASP
     uses to generate Session IDs <xref target="I-D.ietf-anima-grasp"/>. Another possible
     implementation is to hash the name of the
     ASA with a locally defined secret key.</t> 

     <t>In some calls, a 'session_nonce' parameter is required. This is an opaque data structure as far as the ASA is concerned,
     used to identify calls to the API as belonging to a specific GRASP session. In fully threaded implementations this parameter
     might not be needed, but it is included to act as a session handle if necessary. It will also allow GRASP to detect and ignore
     malicious calls or calls from timed-out sessions. A possible implementation is to form the nonce from the underlying
     GRASP Session ID and the source address of the session.</t>

      
      <t>Other parameters are described in the following sections.</t>
      
      </section>
      

      
        <section title="Registration">
        <t>These functions are used to register an ASA and the objectives that it supports with
        the GRASP module. If an authorization model is added to GRASP, it would be added here.</t>
        <t><list style="symbols">

      
            <t>register_asa()<list style="none">
             <t>Input parameter:<list style="hanging">
              <t>name of the ASA (UTF-8 string)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: asa_nonce (integer)</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This initialises state in the GRASP module for the calling entity (the ASA).
               In the case of success, an 'asa_nonce' is returned which the ASA must present in
               all subsequent calls. 
               In the case of failure, the ASA has not been authorized and cannot operate.</t>
            </list></t>
            
            <t>deregister_asa()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>name of the ASA (UTF-8 string)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: none</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This removes all state in the GRASP module for the calling entity (the ASA),
             and deregisters any objectives it has registered. Note that these actions must
             also happen automatically if an ASA crashes.</t>
             <t>Note - the ASA name is strictly speaking redundant in this call, but is present for clarity.</t>
            </list></t>
            
            <t>register_objective()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              <t>discoverable (Boolean - default False)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: none</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This registers an objective that this ASA supports and may modify.
                The 'objective' becomes a candidate for discovery. However, discovery
                responses should not be enabled until the ASA calls listen_negotiate() or
                listen_synchronize(), showing that it is able to act as a responder.
                This can be overridden by setting the optional parameter 'discoverable' to True,
                intended for objectives that are only defined for GRASP discovery,
                and which do not support negotiation or synchronization.
                The ASA may negotiate the objective or send synchronization or flood data.
                Registration is not needed if the ASA only wants to receive synchronization
                or flood data for the objective concerned. This call may be repeated for multiple objectives.</t>
            </list></t>
            
            <t>deregister_objective()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: none</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>The 'objective' must have been registered by the calling ASA; if not, this call fails. 
             Otherwise, it removes all state in the GRASP module for the given objective.</t>
            </list></t>
            
          </list></t> <!-- End of registration functions -->
        </section>
        
        <section title="Discovery">
        <t><list style="symbols">
            <t>discover()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              <t>timeout (integer)</t>
              <t>flush (Boolean - default False)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>locator_list (structure)</t>
              </list></t>
             <t>This returns a list of discovered 'ASA_locator's for the given objective.
             If the optional parameter 'flush' is True, any locally cached locators for the
             objective are deleted first. Otherwise, they are returned immediately. If not,
             GRASP discovery is performed, and all results obtained before the timeout expires
             are returned. If no results are obtained, an empty list is returned after the timeout.</t>
             <t>This should be called in a separate thread if asynchronous operation is required.</t>
            </list></t>        
        </list></t>
        </section> <!-- End of discovery functions -->

        <section title="Negotiation">
        <t><list style="symbols">
           <t>request_negotiate()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              <t>peer (ASA_locator)</t>
              <t>timeout (integer)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>session_nonce (structure)</t>
              <t>result
               <list style="hanging">
               <t>if success: objective (structure)</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This function opens a negotiation session. The 'objective' parameter must
             include the requested value, and its loop count should be set to a
             suitable value by the ASA. If not, the GRASP default will apply.</t>
             <t>The 'peer' parameter is the target node; it must be an 'ASA_locator' as returned
             by discover(). If the peer is null, GRASP discovery is performed first.</t>
             <t>If the 'success' parameter is 'true', the negotiation has successfully
             started. There are then two cases:
              <list style="numbers">
              <t>The 'session_nonce' parameter is null. In this case the negotiation
              has succeeded (the peer has accepted the request). The returned
              objective contains the value accepted by the peer.</t>
              <t>The 'session_nonce' parameter is not null. In this case negotiation
              must continue. The returned objective contains the first value proffered
              by the negotiation peer. Note that this instance of the objective
              must be used in the subsequent negotiation call because
              it also contains the current loop count. The 'session_nonce' must be
              presented in all subsequent negotiation steps. 
              <vspace blankLines="1"/>
              This function must be followed by calls to 'negotiate_step' and/or 'negotiate_wait'
              and/or 'end_negotiate' until the negotiation ends. 'request_negotiate' may then be called
              again to start a new negotation.</t>
              </list></t>
             <t>If the 'success' parameter is 'false', the negotiation has failed
             for the reason given in the result parameter. An exponential backoff
             is recommended before any retry.</t>
             <t>This should be called in a separate thread if asynchronous operation is required.</t>
             <t>Special note for the ACP infrastructure ASA: It is likely that this ASA will need to
             discover and negotiate with its peers in each of its on-link neighbors. It will therefore need to
             know not only the link-local IP address but also the physical interface and transport port for
             connecting to each neighbor. One implementation approach to this is to include these
             details in the 'session_nonce' data structure, which is opaque to normal ASAs.</t>
            </list></t>
            
            <t>listen_negotiate()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: session_nonce (structure)</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
               <t>requested_objective (structure)</t>
             </list></t>
             <t>This function instructs GRASP to listen for negotiation
             requests for the given 'objective'. It also enables discovery responses for the objective.
             It will block waiting for an incoming request, so
             should be called in a separate thread if asynchronous operation is required. Unless
             there is an unexpected failure, 
             this call only returns after an incoming negotiation request. When it does so,
             'requested_objective' contains the first value requested by
             the negotiation peer. Note that this instance of the objective
             must be used in the subsequent negotiation call because
             it also contains the current loop count. The 'session_nonce' must be
             presented in all subsequent negotiation steps. </t>
             <t>This function must be followed by calls to 'negotiate_step' and/or 'negotiate_wait'
             and/or 'end_negotiate' until the negotiation ends. 'listen_negotiate' may then be called
             again to await a new negotation.</t>
             <t>If an ASA is capable of handling multiple negotiations simultaneously, it may
             call 'listen_negotiate' simultaneously from multiple threads. The API and GRASP implementation
             must support re-entrant use of the listening state and the negotiation calls. Simultaneous
             sessions will be distinguished by the threads themselves, the GRASP Session IDs, and the underlying unicast
             transport sockets.</t>
            </list></t>
            
           <t>stop_listen_negotiate()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: null</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>Instructs GRASP to stop listening for negotiation
             requests for the given objective, i.e., cancels 'listen_negotiate'. Of course, it must be called
             from a different thread. </t>
            </list></t>
            
             <t>negotiate_step()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>session_nonce (structure)</t>
              <t>objective (structure)</t>
              <t>timeout (integer)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>Exactly as for 'request_negotiate'</t>
             </list></t>
             <t>Executes the next negotation step with the peer. The 'objective' parameter
             contains the next value being proffered by the ASA in this step.</t>
            </list></t>
            
             <t>negotiate_wait()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>session_nonce (structure)</t>
              <t>timeout (integer)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: null</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>Delay negotiation session by 'timeout' milliseconds.</t>
            </list></t>
  
             <t>end_negotiate()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>session_nonce (structure)</t>
              <t>reply (Boolean)</t>
              <t>reason (UTF-8 string)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: null</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>End the negotiation session.
             <vspace blankLines="1"/>
             'reply' = True for accept (successful negotiation), False for decline (failed negotiation).
             <vspace blankLines="1"/>
             'reason' = optional string describing reason for decline.</t>
            </list></t>
            
        </list></t>        
        </section> <!-- End of negotiation functions -->
        
        <section title="Synchronization and Flooding">
        <t><list style="symbols">

            <t>synchronize()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              <t>peer (ASA_locator)</t>
              <t>timeout (integer)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: objective (structure)</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This call requests the synchronized value of the given 'objective'.</t>
             <t>If the objective was already flooded, the flooded value is
             returned immediately in the 'result' parameter. In this case, the 'source' 
             and 'timeout' are ignored.</t>
             <t> Otherwise, synchronization with a discovered ASA is performed. 
             The 'peer' parameter is an 'ASA_locator' as returned by discover().
             If 'peer' is null, GRASP discovery is performed first.</t>
             <t>This call should be repeated whenever the latest value is needed.</t>
             <t>Call in a separate thread if asynchronous operation is required.</t>
             <t>Since this is essentially a read operation, any ASA can use
             it. Therefore GRASP checks that the calling ASA is registered but the
             objective doesn't need to be registered by the calling ASA.</t>
             <t>In the case of failure, an exponential backoff is recommended before retrying.</t>
            </list></t>
            
            <t>listen_synchronize()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: null</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This instructs GRASP to listen for synchronization
             requests for the given objective, and to
             respond with the value given in the 'objective' parameter.
             It also enables discovery responses for the objective.</t>
             <t>This call is non-blocking and may be repeated whenever the value changes.</t>
            </list></t>
            
            <t>stop_listen_synchronize()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objective (structure)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (Boolean)</t>
              <t>result
               <list style="hanging">
               <t>if success: null</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This call instructs GRASP to stop listening for synchronization
             requests for the given 'objective', i.e. it cancels a previous listen_synchronize.</t>
            </list></t>
            
            <t>flood()<list style="none">
             <t>Input parameters:<list style="hanging">
              <t>asa_nonce (integer)</t>
              <t>objectives (type)</t>
              </list></t>
             <t>Return parameters:<list style="hanging">
              <t>success (type)</t>
              <t>result (type)
               <list style="hanging">
               <t>if success: name (type)</t>
               <t>if not success: error message (UTF-8 string) </t>
               </list></t>
             </list></t>
             <t>This call instructs GRASP to flood the given synchronization
             objective(s) and their value(s) to all GRASP nodes.
             The 'objectives' parameter is a list of one or more objectives.</t>
             <t>Checks that the ASA registered each objective.</t>
             <t>This call may be repeated whenever any value changes.</t>
            </list></t>
            
        </list></t>
        </section> <!-- End of synchronization functions -->
        
 
      </section>
    </section>
    
    <section anchor="examples" title="Example Logic Flows">
    <t>TBD</t>
    <t>(Until this section is written, some Python examples can be found at
    <eref target="https://www.cs.auckland.ac.nz/~brian/graspy/Briggs.py"/>
    and
    <eref target="https://www.cs.auckland.ac.nz/~brian/graspy/Gray.py"/>.)
    </t>
    </section>

    <!---->

    <section anchor="security" title="Security Considerations">
      <t>Security issues for the GRASP protocol are discussed in <xref target="I-D.ietf-anima-grasp"/>.
      Authorization of ASAs is a subject for future study.</t>
      <t>The 'asa_nonce' parameter is used in the API as a first line of defence against a malware process attempting
      to imitate a legitimately registered ASA. The 'session_nonce' parameter is used in the API as a first line
      of defence against a malware process attempting to hijack a GRASP session. </t>
    </section>

    <section anchor="iana" title="IANA Considerations">
      <t>This does not need IANA assignment.</t>

      <t/>
    </section>

    <section anchor="ack" title="Acknowledgements">
      <t>This document was produced using the xml2rfc tool <xref target="RFC7749"/>.</t>
    </section>
  </middle>
  <back>
    <references title="Normative References">
      <!-- <?rfc include='reference.RFC.2119'?> -->

      <?rfc include='reference.I-D.ietf-anima-grasp'?>
    </references>

    <references title="Informative References">
    
      <?rfc include='reference.RFC.7749'?>
      <?rfc include='reference.I-D.ietf-anima-reference-model'?>
      <?rfc include='reference.I-D.liu-anima-grasp-distribution'?>
    </references>
  </back>
</rfc>
