Folks: Version 1.0 of the ALTO interoperability document is
attached.
The test document is now complete. We have 20 test cases (test cases
19 and 20 were contributed by Ning Zhang).
Barring any errors in representation and interpretation of
the test cases contained therein, this document will be used
to drive the interoperability event on Monday.
Please let me know if you have any questions and or comments.
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 1.0)
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 /endpoints/property 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 /endpoints/property 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 /endpoints/property 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 /endpoints/cost 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 Case 1: Retreiving PIDs.
- Client retrieves a PID for an IPv6 and IPv4 address.
Use the following request:
POST /endpoints/property HTTP/1.1
Host: alto.ietf.org
Content-Length: 106
Accept: application/alto-endpointprop+json
{
"properties" : [ "pid" ],
"endpoints" : [ "ipv6:1234::192.168.1.23", "ipv6:2001:DB8::2345:5678" ]
}
- Server responds with the following:
HTTP/1.1 200 OK
Content-Type: application/alto-endpointprop+json;charset=UTF-8
Content-Length: 157
{
"meta" : { } ,
"data" : {
"ipv6:1234::192.168.1.23" : { "pid" : "defaultpid " } ,
"ipv6:2001:DB8::2345:5678" : { "pid" : "peeringpid2" }
}
}
20) IPv6 Test Case 2: Endpoint cost service for IPv6 and IPv4 addresses.
- Client sends a request to get cost information between
individual endpoints.
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: 235
{
"cost-mode" : "ordinal",
"cost-type" : "routingcost",
"endpoints" : {
"srcs": [ "ipv6:2001:DB8::ABCD:6789", "ipv4:192.168.10.1" ],
"dsts": [
"ipv6:2001:DB8::2345:5678",
"ipv6:2003::192.168.10.1"
]
}
}
- Server responds with the following:
HTTP/1.1 200 OK
Content-Type: application/alto-endpointcost+json;charset=UTF-8
Content-Length: 239
{
"meta" : { } ,
"data" : {
"cost-type" : "routingcost" ,
"cost-mode" : "ordinal" ,
"map" : {
"ipv4:192.168.10.1" : {
"ipv6:2001:DB8::2345:5678" : 1 ,
"ipv6:2003::192.168.10.1" : 2
}
}
}
}
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]>
Ning Zhang <[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 1.0)
_______________________________________________
alto mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/alto