Folks: Attached is the latest version of the ALTO document
based on list feedback over the last couple of days.

The URIs in the information directory now match the URIs
shown in subsequent examples.  Assorted typos and missing
commas or brackets have been fixed.

All those folks who were generous enough to review the
previous versions kindly check to make sure that their
reviews have been adequately attended to.

Thanks,

- vijay
--
Vijay K. Gurbani, Bell Laboratories, Alcatel-Lucent
1960 Lucent Lane, Rm. 9C-533, Naperville, Illinois 60566 (USA)
Email: vkg@{bell-labs.com,acm.org} / [email protected]
Web:   http://ect.bell-labs.com/who/vkg/
---- BEGIN ALTO INTEROPERABILITY DOCUMENT (Version 0.91)

For the ALTO interoperability, we will consider the following topology
from the view point of a service provider:

PID            IP Address Block
-------------------------------
mypid1         10.0.0.0/8, 15.0.0.0/8
mypid2         192.168.0.0/16
mypid3         192.168.10.0/24
peeringpid1    128.0.0.0/16
peeringpid2    130.0.0.0/16, 2001:DB8::/32
transitpid1    132.0.0.0/16
transitpid2    135.0.0.0/16
defaultpid     0.0.0.0/0, ::/0

And here is the cost map for the above topology:

Source PID         Destination PID            Cost (mode: numerical)
--------------------------------------------------------------------
mypid1             mypid1                               0
  "                mypid2                               0
  "                mypid3                               0
  "                peeringpid1                          0
  "                peeringpid2                          0
  "                transitpid1                          5
  "                transitpid2                         10
  "                defaultpid                           4
mypid2             mypid1                               0
  "                mypid2                               0
  "                mypid3                               0
  "                peeringpid1                          0
  "                peeringpid2                          0
  "                transitpid1                          7
  "                transitpid2                          8
  "                defaultpid                           4
mypid3             mypid1                               0
  "                mypid2                               0
  "                mypid3                               0
  "                peeringpid1                          0
  "                peeringpid2                          0
  "                transitpid1                          8
  "                transitpid2                          8
  "                defaultpid                           5.1

Test Cases are described below.  Note that it is not expected that
all client and server implementations generate requests and
responses in the same format as shown below.  The syntax related
to representing each request or response is left to each individual 
implementation as long as the payload is syntactically valid and 
semantically equivalent to any other representation of the same payload.

1) Retrieving the Information Resource Directory (IRD, Section 7.6)
   - Client retrieve IRD through a well known URI: 
        http://alto.ietf.org/directory
     using a request shown below:

   GET /directory HTTP/1.1
   Host: alto.ietf.org
   Accept: application/alto-directory+json,application/alto-error+json

   - Server returns the following directory, or one with equivalent
     information resources:

   HTTP/1.1 200 OK
   Content-Length: 2596
   Connection: close
   Content-Type: application/alto-directory+json
   Date: Wed, 29 Jun 2011 10:52:09 GMT

   {
   "resources": [
      {
         "capabilities": {
            "cost-modes": [
               "numerical"
            ],
            "cost-types": [
               "routingcost"
            ]
         },
         "media-types": [
            "application/alto-costmap+json"
         ],
         "uri": "http://alto.ietf.org/costmap/numerical/routingcost";
      },
      {
         "capabilities": {
            "cost-modes": [
               "ordinal"
            ],
            "cost-types": [
               "routingcost"
            ]
         },
         "media-types": [
            "application/alto-costmap+json"
         ],
         "uri": "http://alto.ietf.org/costmap/ordinal/routingcost";
      },
      {
         "media-types": [
            "application/alto-networkmap+json"
         ],
         "uri": "http://alto.ietf.org/networkmap";
      },
      {
         "media-types": [
            "application/alto-serverinfo+json"
         ],
         "uri": "http://alto.ietf.org/serverinfo";
      },
      {
         "accepts": [
            "application/alto-costmapfilter+json"
         ],
         "capabilities": {
            "cost-constraints": true,
            "cost-modes": [
               "numerical",
               "ordinal"
            ],
            "cost-types": [
               "routingcost"
            ]
         },
         "media-types": [
            "application/alto-costmap+json"
         ],
         "uri": "http://alto.ietf.org/costmap/filtered";
      },
      {
         "accepts": [
            "application/alto-endpointcostparams+json"
         ],
         "capabilities": {
            "cost-constraints": true,
            "cost-modes": [
               "numerical",
               "ordinal"
            ],
            "cost-types": [
               "routingcost"
            ]
         },
         "media-types": [
            "application/alto-endpointcost+json"
         ],
         "uri": "http://alto.ietf.org/endpoints/cost";
      },
      {
         "accepts": [
            "application/alto-endpointpropparams+json"
         ],
         "capabilities": {
            "prop-types": [
               "pid"
            ]
         },
         "media-types": [
            "application/alto-endpointprop+json"
         ],
         "uri": "http://alto.ietf.org/endpoints/property";
      },
      {
         "accepts": [
            "application/alto-networkmapfilter+json"
         ],
         "media-types": [
            "application/alto-networkmap+json"
         ],
         "uri": "http://alto.ietf.org/networkmap/filtered";
      }
   ]
   }

2) Longest prefix match (c.f. Section 4.2.1)

   - Client retrieves a PID for IP address 192.168.1.23
     Use the following request:

     POST /endpointprop/lookup HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Accept: application/alto-endpointprop+json

     {
        "properties" : [ "pid" ],
        "endpoints" : [ "ipv4:192.168.1.23" ]
      }

   - Server returns mypid2 using the following response:

   HTTP/1.1 200 OK
   Content-Length: ...
   Content-Type: application/alto-endpointprop+json

   {
     "meta" : {},
     "data": {
       "ipv4:192.168.1.23"    : { "pid": "mypid2" }
     }
   }

3) Longest prefix match (c.f. Section 4.2.1)

   - Client retrieves a PID for IP address 192.168.10.23
     Use the following request:

     POST /endpointprop/lookup HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Accept: application/alto-endpointprop+json

     {
        "properties" : [ "pid" ],
        "endpoints" : [ "ipv4:192.168.10.23" ]
      }

   - Server returns mypid3 using the following response:

   HTTP/1.1 200 OK 
   Content-Length: ...
   Content-Type: application/alto-endpointprop+json

   { 
     "meta" : {},
     "data": {
       "ipv4:192.168.10.23"    : { "pid": "mypid3" }
     } 
   } 

4) Returning default PID:

   - Client retrieves a PID for IP address 201.1.13.12
     Use the following request:

     POST /endpointprop/lookup HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Accept: application/alto-endpointprop+json

     {
        "properties" : [ "pid" ],
        "endpoints" : [ "ipv4:201.1.13.12" ]
      }

   - Server returns defaultpid using the following response:

   HTTP/1.1 200 OK
   Content-Length: ...
   Content-Type: application/alto-endpointprop+json

   { 
     "meta" : {},
     "data": {
       "ipv4:201.1.13.12"    : { "pid": "defaultpid" }
     }
   }

5) Retrieving a network map (Section 4, Section 7.7.2)
  
   - Client uses information from IRD to retrieve a network map.
     Use the following request:

     GET /networkmap HTTP/1.1
     Host: alto.ietf.org
     Accept: application/alto-networkmap+json,application/alto-error+json

   - Server returns the following:

   HTTP/1.1 200 OK
   Content-Length: 799   
   Content-Type: application/alto-networkmap+json

   {
      "meta" : {},
      "data" : {
         "map-vtag" : "1266506139",
         "map" : {
            "mypid1" : {
               "ipv4" : [ "10.0.0.0/8", "15.0.0.0/8" ]
            },
            "mypid2" : {
               "ipv4" : [ "192.168.0.0/16" ]
            },
            "mypid3" : {
               "ipv4" : [ "192.168.10.0/24" ]
            },
            "peeringpid1" : {
               "ipv4" : [ "128.0.0.0/16" ]
            },
            "peeringpid2" : {
               "ipv4" : [ "130.0.0.0/16" ],
               "ipv6" : [ "2001:DB8::/32"]
            },
            "transitpid1" : {
               "ipv4" : [ "132.0.0.0/16" ]
            },
            "transitpid2" : {
               "ipv4" : [ "135.0.0.0/16" ]
            },
            "defaultpid" : {
               "ipv4" : [ "0.0.0.0/0" ],
               "ipv6" : [ "::/0" ]
            }
         }
      }
   }

6) Retrieving a cost map (Section 5)

   - Client uses information from IRD to retrieve a cost map.
     Use the following request:

   GET /costmap/numerical/routingcost HTTP/1.1
   Host: alto.ietf.org
   Accept: application/alto-costmap+json,application/alto-error+json
  
   - Server returns the following:

   HTTP/1.1 200 OK
   Content-Length: 787
   Content-Type: application/alto-costmap+json

   {
     "meta" : {},
     "data" : {
       "cost-mode" : "numerical",
       "cost-type" : "routingcost",
       "map-vtag"  : "1266506139",
       "map" : {
         "mypid1": { "mypid1" : 0,  "mypid2" : 0,  "mypid3" : 0,
                     "peeringpid1" : 0, "peerinpid2" :  0,
                     "transitpid1" : 5, "transitpid2" : 10,
                     "defaultpid" : 4},
         "mypid2": { "mypid1" : 0,  "mypid2" : 0,  "mypid3" : 0,
                     "peeringpid1" : 0, "peerinpid2" :  0,
                     "transitpid1" : 7, "transitpid2" : 8,
                     "defaultpid" : 4},
         "mypid3": { "mypid1" : 0,  "mypid2" : 0,  "mypid3" : 0,
                     "peeringpid1" : 0, "peerinpid2" :  0,
                     "transitpid1" : 8, "transitpid2" : 8,
                     "defaultpid" : 5.1}
       }
     }
   }

   NOTE: Make sure that the vtag in the response for the cost
   map is the same as the vtag in the response for Test case 5.

7) Error: JSON parsing error (Section 7)

   - Client sends a malformed JSON body in the request --- a missing
     closing '}'
     Use the following request:

   POST /endpoints/cost HTTP/1.1
   Host: alto.ietf.org
   Accept: application/alto-endpointcost+json,application/alto-error+json
   Content-Type: application/alto-endpointcostparams+json
   Content-Length: 131

   { 
        "cost-mode" : "numerical", 
        "cost-type" : "routingcost", 
        "endpoints": { 
                "srcs": [ "ipv4:10.0.0.0"], 
                "dsts": [ "ipv4:10.0.0.0" ] 
        } 

   - Server returns HTTP response code of 400 with ALTO error code 
     of E_SYNTAX (c.f., Table 1):

   HTTP/1.1 400 Bad Request
   Content-Type: application/alto-error+json
   Content-Length: 60

   { 
        "code": "E_SYNTAX", 
        "reason": "Parsing error in request" 
   }

   Note that a server implementation can provide a more descriptive
   phrase, if desired.  For instance, in the above example, a 
   reason phrase of "Parsing error: Missing closing brace" may be
   more descriptive.
   
8) Error: Required field missing (Section 7)

   - Client sends a request with a missing field --- no "cost-mode".
     Use the following request:

   POST /endpoints/cost HTTP/1.1
   Host: alto.ietf.org
   Accept: application/alto-endpointcost+json,application/alto-error+json
   Content-Type: application/alto-endpointcostparams+json
   Content-Length: 105

   { 
        "cost-type" : "routingcost", 
        "endpoints": { 
                "srcs": [ "ipv4:10.0.0.0"], 
                "dsts": [ "ipv4:10.0.0.0" ] 
        } 
   }

   - Server returns HTTP response code of 400 with ALTO error code 
     of E_JSON_FIELD_MISSING (c.f., Table 1):

   HTTP/1.1 400 Bad Request
   Content-Type: application/alto-error+json
   Content-Length: 70

   { 
        "code": "E_JSON_FIELD_MISSING", 
        "reason": "Required field missing" 
   }

   Note that as in Test Case 7, a server may provide a descriptive
   reason phrase.  In this particular example, a reason phrase of
   "Missing mandatory field: cost-mode" may be more descriptive.
  
9) Error: Unexpected JSON value (Section 7)

   - Client sends a request with a JSON value of unexpected type ---
     object "srcs" is not an array type.
     Use the following request:

   POST /endpoints/cost HTTP/1.1
   Host: alto.ietf.org
   Accept: application/alto-endpointcost+json,application/alto-error+json
   Content-Type: application/alto-endpointcostparams+json
   Content-Length: 129

   { 
        "cost-mode" : "numerical", 
        "cost-type" : "routingcost", 
        "endpoints": {
                "srcs":"ipv4:10.0.0.0" , 
                "dsts": [ "ipv4:10.0.0.0" ] 
        } 
   } 

   - Server returns HTTP response code of 400 with ALTO error code 
     of E_JSON_VALUE_TYPE (c.f., Table 1):

   HTTP/1.1 400 Bad Request
   Content-Type: application/alto-error+json
   Content-Length: 74

   { 
        "code": "E_JSON_VALUE_TYPE", 
        "reason": "JSON value of unexpected type" 
   }

10) Error: Invalid JSON cost mode (Section 7)

   - Client sends a request with a cost mode of 'foo'

     POST /costmap/filtered HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Content-Type: application/alto-costmapfilter+json
     Accept: application/alto-costmap+json

     {
       "cost-mode": "foo",
       "cost-type": "routingcost",
       "pids": {
          "dsts": [],
          "srcs": []
       }
     }

   - Server returns HTTP response code of 400 with ALTO error code 
     of E_JSON_COST_MODE (c.f., Table 1).

     HTTP/1.1 400 Bad Request
     Content-Length: ...
     Content-Type: application/alto-error+json

     {
       "code": "E_INVALID_COST_MODE",
       "reason": "Invalid cost mode"
     }

11) Error: Invalid JSON cost type (Section 7)

   - Client sends a request with a cost type of 'foo'

     POST /costmap/filtered HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Content-Type: application/alto-costmapfilter+json
     Accept: application/alto-costmap+json

     {
       "cost-mode": "numerical",
       "cost-type": "foo",
       "pids": {
          "dsts": [],
          "srcs": []
       }
     }

   - Server returns HTTP response code of 400 with ALTO error code 
     of E_JSON_COST_TYPE (c.f., Table 1).

     HTTP/1.1 400 Bad Request
     Content-Length: ...
     Content-Type: application/alto-error+json

     {
       "code": "E_INVALID_COST_TYPE",
       "reason": "Invalid cost type"
     }

12) Error: Invalid JSON property type (Section 7)

   - Client sends a request with an invalid property type ('foo')
     for IP address 10.0.0.1:

     POST /endpoints/property HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Content-Type: application/alto-endpointpropparams+json
     Accept: application/alto-endpointprop+json

     {
       "endpoints": ["ipv4:10.0.0.1"],
       "properties": ["foo"]
     }

   - Server returns HTTP response code of 400 with ALTO error code 
     of E_JSON_PROPERTY_TYPE (c.f., Table 1).

     HTTP/1.1 400 Bad Request
     Content-Length: ...
     Content-Type: application/alto-error+json

     {
       "code": "E_INVALID_PROPERTY_TYPE",
       "reason": "Invalid property type"
     }

13) Error: multiple errors in request (Section 7)

    - Client sends a request with an invalid cost and type and mode
      ('foo' and 'bar' respectively):

     POST /costmap/filtered HTTP/1.1
     Host: alto.ietf.org
     Content-Length: ...
     Content-Type: application/alto-costmapfilter+json
     Accept: application/alto-costmap+json

     {
       "cost-mode": "bar",
       "cost-type": "foo",
       "pids": {
          "dsts": [],
          "srcs": []
       }
     }

    - Server should detect at least one error and return that in a 
      response.  The server chooses which error to report.

     HTTP/1.1 400 Bad Request
     Content-Length: ...
     Content-Type: application/alto-error+json

     {
       "code": "E_INVALID_COST_TYPE",
       "reason": "Invalid cost type"
     }

     Question: If the server is capable of detecting and reporting
     multiple errors, then what?  How does it let the client know?

14) Error: send a request with a bad URI

    - Client sends the following request:

      GET /foo/bar HTTP/1.1
      Host: alto.ietf.org
      Accept: application/alto-costmap+json,application/alto-error+json

    - Server responds with:

      HTTP/1.1 404 Not Found
      Content-Length: 0
      

15) Change in network map (Section 5.3)

    - Add a new network, changing the map.  For example, add the following
      subnet 201.1.2.0/24 to peeringpid2 giving the new network map entry
      for peeringpid2 as follows:
      
      peeringpid2    130.0.0.0/16, 2001:DB8::/32, 201.1.2.0/24

    - Have a client retrieve the new network map.

    - The Version tag on the network map should be different than the
      one retrieved in Test Case 5.

    - The server will respond with the following:

   HTTP/1.1 200 OK
   Content-Length: 827
   Content-Type: application/alto-networkmap+json

   {
      "meta" : {},
      "data" : {
         "map-vtag" : "1266506155",
         "map" : {
            "mypid1" : {
               "ipv4" : [ "10.0.0.0/8", "15.0.0.0/8" ]
            },
            "mypid2" : {
               "ipv4" : [ "192.168.0.0/16" ]
            },
            "mypid3" : {
               "ipv4" : [ "192.168.10.0/24" ]
            },
            "peeringpid1" : {
               "ipv4" : [ "128.0.0.0/16" ]
            },
            "peeringpid2" : {
               "ipv4" : [ "130.0.0.0/16" ],
               "ipv4" : [ "201.1.2.0/24" ],
               "ipv6" : [ "2001:DB8::/32"]
            },
            "transitpid1" : {
               "ipv4" : [ "132.0.0.0/16" ]
            },
            "transitpid2" : {
               "ipv4" : [ "135.0.0.0/16" ]
            },
            "defaultpid" : {
               "ipv4" : [ "0.0.0.0/0" ],
               "ipv6" : [ "::/0" ]
            }
         }
      }
   }

16) Filtered network map (Section 7.7.3)

   - Client sends a request to get a filtered map of mypid2:
   Use the following request:

   POST /networkmap/filtered HTTP/1.1
   Host: alto.ietf.org
   Content-Length: 26
   Content-Type: application/alto-networkmapfilter+json
   Accept: application/alto-networkmap+json,application/alto-error+json

   {
     "pids": [ "mypid2" ]
   }

  - Server returns the following response:

   HTTP/1.1 200 OK
   Content-Length: 172
   Content-Type: application/alto-networkmap+json

   {
      "meta" : {},
      "data" : {
         "map-vtag" : "1266506155",
         "map" : {
            "mypid2" : {
               "ipv4" : [ "192.168.0.0/16" ]
            }
         }
      }
   }

17) Filtered cost map (Section 7.7.3.2, Section 7.7.2.2)
    
    - Client sends a request to get a filtered cost map from a source
      PID to a set of destination PIDs.
      Use the following request:

   POST /costmap/filtered HTTP/1.1
   Host: alto.ietf.org
   Content-Type: application/alto-costmapfilter+json
   Content-Length: 174
   Accept: application/alto-costmap+json,application/alto-error+json

   {
     "cost-mode" : "numerical",
     "cost-type" : "routingcost",
     "pids" : {
       "srcs" : [ "mypid1", "mypid3" ],
       "dsts" : [ "mypid2", "peeringpid1", "transitpid2" ]
     }
   }

  - Server responds with the following:

   HTTP/1.1 200 OK
   Content-Length: 294
   Content-Type: application/alto-costmap+json

   {
     "meta" : {},
     "data" : {
       "cost-mode" : "numerical",
       "cost-type" : "routingcost",
       "map-vtag" : "1266506155",
       "map" : {
         "mypid1": { "mypid2": 0,  "peeringpid1": 0,  "transitpid2": 10 },
         "mypid3": { "mypid2": 0,  "peeringpid1": 0,  "transitpid2": 8 }
       }
     }
   }

18) Endpoint cost service (Section 7.7.5)
    
    - Client sends a request to get cost information between
      individual endpoints.
      Use the following request:

   POST /endpointcost/lookup HTTP/1.1
   Host: alto.example.com
   Content-Length: 428
   Content-Type: application/alto-endpointcostparams+json
   Accept: application/alto-endpointcost+json,application/alto-error+json

   {
       "cost-mode" : "numerical",
       "cost-type" : "routingcost",
       "endpoints" : {
         "srcs": [ "ipv4:10.0.0.0", "ipv4:192.168.11.0", "ipv4:192.168.10.0"],
         "dsts": [
           "ipv4:10.0.0.0",
           "ipv4:15.0.0.0",
           "ipv4:192.168.11.0",
           "ipv4:192.168.10.0",
           "ipv4:128.0.0.0",
           "ipv4:130.0.0.0",
           "ipv4:0.0.0.0",
           "ipv4:132.0.0.0",
           "ipv4:135.0.0.0" 
         ]
       }
   }

   - Server responds with the following:

   HTTP/1.1 200 OK
   Content-Length: 1692
   Content-Type: application/alto-endpointcost+json

   {
      "meta": { },
      "data": {
                "cost-mode": "numerical",
                "cost-type": "routingcost",
                "map": {
                       "ipv4:10.0.0.0": {
                        "ipv4:10.0.0.0": 0.000000,
                        "ipv4:15.0.0.0": 0.000000,
                        "ipv4:192.168.11.0": 0.000000,
                        "ipv4:192.168.10.0": 0.000000,
                        "ipv4:128.0.0.0": 0.000000,
                        "ipv4:130.0.0.0": 0.000000,
                        "ipv4:0.0.0.0": 4.000000,
                        "ipv4:132.0.0.0": 5.000000,
                         "ipv4:135.0.0.0": 10.000000
                    },
                    "ipv4:192.168.11.0": {
                         "ipv4:10.0.0.0": 0.000000,
                         "ipv4:15.0.0.0": 0.000000,
                         "ipv4:192.168.11.0": 0.000000,
                         "ipv4:192.168.10.0": 0.000000,
                         "ipv4:128.0.0.0": 0.000000,
                         "ipv4:130.0.0.0": 0.000000,
                         "ipv4:0.0.0.0": 4.000000,
                         "ipv4:132.0.0.0": 7.000000,
                         "ipv4:135.0.0.0": 8.000000
                    },
                    "ipv4:192.168.10.0": {
                          "ipv4:10.0.0.0": 0.000000,
                          "ipv4:15.0.0.0": 0.000000,
                          "ipv4:192.168.11.0": 0.000000,
                          "ipv4:192.168.10.0": 0.000000,
                          "ipv4:128.0.0.0":0.000000,
                          "ipv4:130.0.0.0": 0.000000,
                          "ipv4:0.0.0.0": 5.100000,
                          "ipv4:132.0.0.0": 8.000000,
                          "ipv4:135.0.0.0": 8.000000
                    }
                }
      }
   }

19)  IPv6 test cases
     (TBD)

Miscellaneous notes

1) Section 4.2.1 says that "Each endpoint MUST map into exactly one PID."

   What happens if a client finds out that the above is not true?

   Update: This is being debated on the mailing list right now.

Acknowldegements:

Many thanks to the following individuals who submitted the details of 
test cases outlined in this document.

Manish <[email protected]>
Bill Roome <[email protected]>

Many thanks to the following individuals who reviewed the test cases 
and submitted feedback to correct typos and other errors.

Richard Alimi <[email protected]>
Mikio Hara <[email protected]>
Ning Zhang <[email protected]>

If I have inadvertently omitted someone, please let me know.

Vijay K. Gurbani <[email protected]>
---- END ALTO INTEROPERABILITY DOCUMENT (Version 0.91)
_______________________________________________
alto mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/alto

Reply via email to