Dear all,
We are revising the ALTO base protocol. One item that we are considering to
change is some clarification of the specification schema for the base
protocol. Attached is a proposed schema. The changes and their impacts are
the following:
- Change 1.
We added a new schema called object-map. The basic problem that we are
trying to solve is the "ambiguity" of JSON deserialization. Specifically,
an JSON object { "a1":"v1", "a2":"v2"} can have interpretations: it is an
object of type
object {
String a1;
String a2;
}
or a HashMap object from strings to strings.
Now consider the encoding of a network map:
"map" : {
"PID1" : {
"ipv4" : [
"192.0.2.0/24",
"198.51.100.0/24"
]
},
"PID2" : {
"ipv4": [
"198.51.100.128/24"
]
}
}
Now if we use the first interpretation, we need to define many class types,
one for each given number of PIDs. This is too many classes. We also
considered an array like encoding:
"map" : [
{"PID1" : {
"ipv4" : [
"192.0.2.0/24",
"198.51.100.0/24"
]
}},
{"PID2" : {
"ipv4": [
"198.51.100.128/24"
]
}}
}
But this reads ugly according to several. Hence, we decided to use the
current encoding. But we give a hint that the encoding is better a HashMap
(key/value store), and hence only a single class.
Suppose one uses GSON as a parser, it is quite easy to construct:
// Map<String, EndpointAddrGroup> map
// = gson.fromJson(json,
// new TypeToken<Map<String, EndpointAddrGroup>>()
{}.getType());
IMPACT: It does not change the data format on the wire but conceptually
cleaner.
* Change 2.
We added a new type:
object { // still separate mode and type but syntax
sugar
CostMode mode; // to put in the same object
CostType type;
} CostID;
This is based on the consensus that we separate mode and type. Wendy put
the motivation of change better than I could. So here is her words:
"Here's how I'd describe the change. Before, the cost map request &
response messages had "cost-type" and "cost-mode" fields. Now they have
nested "cost-id.type" and "cost-id.mode" fields. That should be a simple
change for any implementation.
For a full map request, the IRD has a similar straight-forward change: in
the capabilities section, the "cost-type" and "cost-mode" fields have been
replaced by the nested "cost-id.type" and "cost-id.mode" fields.
The major difference is in the IRD entry for a filtered cost map request.
Before the server listed all valid types and modes. Now the server
specifies the valid pairs. The advantage is now the client can tell which
combinations are supported. Before, the client found out the hard way.
And the primary motivation for cost-ids is to resolve that problem with
filtered cost maps. Otherwise cost-ids are syntactic sugar."
IMPACT: Existing implementations need to merge cost-mode and cost-type into
a single object, which is a very minor change.
The authors have not made the final decisions to make the changes. Any
comments are highly welcome!
Richard
// File: ALTO Schema
// Date: 03/14/2013
//***********************************************
//** Information Resource Directory (IRD) grammar
//***********************************************
object {
ResourceEntry resources<0..*>;
} InfoResourceDirectory;
object {
JSONString uri;
JSONString media-types<1..*>;
JSONString accepts<0..*>; [OPTIONAL]
[Capabilities] capabilities; [OPTIONAL; exact type depends
on media-type above;
[Capabilities] denote base class]
} ResourceEntry;
object-map {
String -> JSONValue; // A map object consisting of 0 to
// many entries where each entry maps
// a String to a JSONValue
} Capabilities;
object {
CostID cost-id;
} CostMapCapabilities; // for cost map; single CostID unless we want
// to return multi costs in each entry in future
object { // still separate mode and type but syntax sugar
CostMode mode; // to put in the same object
CostType type;
} CostID;
// FilteredCostMapCapabilities renamed to CostFilteringCapabilities
// CostFilteringCapabilities also uses CostFilteringCapabilities
// A special case of Capabilities
object-map {
"cost-ids" -> CostID<0..*>;// gives an array for request to select
"cost-constraints" -> JSONBool;
} CostFilteringCapabilities;
object-map {
"prop-types" -> EndpointPropertyType <0..*>;
} EndpointPropertyCapabilities;
// Example
GET /directory HTTP/1.1
Host: alto.example.com
Accept: application/alto-directory+json,application/alto-error+json
HTTP/1.1 200 OK
Content-Length: 1472
Content-Type: application/alto-directory+json
{
"resources" : [
{
"uri" : "http://alto.example.com/networkmap",
"media-types" : [ "application/alto-networkmap+json" ]
}, {
"uri" : "http://alto.example.com/costmap/num/routingcost",
"media-types" : [ "application/alto-costmap+json" ],
"capabilities" : {
"cost-id" : {"mode" : "numerical", "type": "routingcost"}
}
}, {
"uri" : "http://alto.example.com/costmap/num/hopcount",
"media-types" : [ "application/alto-costmap+json" ],
"capabilities" : {
"cost-id" : {"mode" : "numerical", "type": "hopcount"}
}
}, {
"uri" : "http://custom.alto.example.com/maps",
"media-types" : [
"application/alto-networkmap+json",
"application/alto-costmap+json"
],
"accepts" : [
"application/alto-networkmapfilter+json",
"application/alto-costmapfilter+json"
]
}, {
"uri" : "http://alto.example.com/endpointprop/lookup",
"media-types" : [ "application/alto-endpointprop+json" ],
"accepts" : [ "application/alto-endpointpropparams+json" ],
"capabilities" : {
"prop-types" : [ "pid" ]
}
}, {
"uri" : "http://alto.example.com/endpointcost/lookup",
"media-types" : [ "application/alto-endpointcost+json" ],
"accepts" : [ "application/alto-endpointcostparams+json" ],
"capabilities" : {
"cost-constraints" : true,
// OLD: comment not part of message
// "cost-modes" : [ "ordinal", "numerical" ],
// "cost-types" : [ "routingcost", "hopcount" ]
// Assume server will not reveal numerical of hopcount
"cost-ids" : [ {"mode":"ordinal", "type":"routingcost"},
{"mode":"numerical","type":"routingcost"},
{"mode":"ordinal", "type":"hopcount"}
]
}
}
]
}
//************************************
//** InformationResource (IR) grammar
//************************************
object {
InfoResourceMetaData meta; [OPTIONAL]
[InfoResourceDataType] data;
} InfoResourceEntity;
// [InfoResourceDataType] has 4 specific types defined for now:
// application determines the type from media-type
// - InfoResourceNetworkMap
// - InfoResourceCostMap
// - InfoResourceEndpointProperty
// - InfoResourceEndpointCostMap
object {
} InfoResourceMetaData;
object {
JSONString code;
} ErrorResourceEntity;
//************************************
// --- IR: Network Map
//************************************
object {
VersionTag map-vtag;
NetworkMapData map;
} InfoResourceNetworkMap;
// comment: discussed an array based encoding of map, but prefer
// the current hash based design for better readability
// The implementation should be still straightforward:
// e.g., using gson:
// Map<String, EndpointAddrGroup> map
// = gson.fromJson(json,
// new TypeToken<Map<String, EndpointAddrGroup>>() {}.getType());
object-map {
// OLD: EndpointAddrGroup [PIDName];
// ...
PIDName -> EndpointAddrGroup; // A map object with each entry mapping
// a PIDName to an EndpointAddrGroup
} NetworkMapData;
object-map {
//EndpointPrefix [AddressType]<0..*>;
//...
// A map object with each entry mapping
// an address type to an array of prefixes
AddressType -> EndpointPrefix<0..*>;
} EndpointAddrGroup;
// Example
HTTP/1.1 200 OK
Content-Length: 255
Content-Type: application/alto-networkmap+json
{
"meta" : {},
"data" : {
"map-vtag" : "1266506139",
"map" : {
"PID1" : {
"ipv4" : [
"192.0.2.0/24",
"198.51.100.0/24"
]
},
"PID2" : {
"ipv4": [
"198.51.100.128/24"
]
}
}
}
}
//************************************
// --- IR: Cost Map
//************************************
object {
CostID cost-id; // comment: define cost-ids<1..*>
// for multi-d in future?
VersionTag map-vtag;
CostMapData map;
} InfoResourceCostMap;
object-map {
// OLD
// DstCosts [PIDName];
//...
// A map object with each entry mapping
// a PIDName to a DstCosts object
PIDName -> DstCosts;
} CostMapData;
object-map DstCosts {
//OLD
// JSONValue [PIDName];
//...
// A map object with each entry mapping
// a PIDName to a JSONValue
PIDName -> JSONValue;
};
// Example
HTTP/1.1 200 OK
Content-Length: 262
Content-Type: application/alto-costmap+json
{
"meta" : {},
"data" : {
"cost-id" : {"mode":"numerical", "type":"routingcost"},
"map-vtag" : "1266506139",
"map" : {
"PID1": { "PID1": 1, "PID2": 5, "PID3": 10 },
"PID2": { "PID1": 5, "PID2": 1, "PID3": 15 },
"PID3": { "PID1": 20, "PID2": 15 }
}
}
}
//*************************************
// --- Request for filtered network map
//*************************************
object {
PIDName pids<0..*>;
AddressType address-types<0..*>;
} ReqFilteredNetworkMap;
// Example: missing address types
POST /networkmap/filtered HTTP/1.1
Host: custom.alto.example.com
Content-Length: 27
Content-Type: application/alto-networkmapfilter+json
Accept: application/alto-networkmap+json,application/alto-error+json
{
"pids": [ "PID1", "PID2" ]
}
//*************************************
// --- Request for filtered cost map
//*************************************
object {
CostID cost-id;
JSONString constraints<0..*>; [OPTIONAL]
PIDFilter pids; [OPTIONAL]
} ReqFilteredCostMap;
object {
PIDName srcs<0..*>;
PIDName dsts<0..*>;
} PIDFilter;
// Example
POST /costmap/filtered HTTP/1.1
Host: custom.alto.example.com
Content-Type: application/alto-costmapfilter+json
Accept: application/alto-costmap+json,application/alto-error+json
{
"cost-id" : {"mode":"numerical", "type":"routingcost"},
"pids" : {
"srcs" : [ "PID1" ],
"dsts" : [ "PID1", "PID2", "PID3" ]
}
}
//*************************************
// --- Request for endpoint properties
//*************************************
object {
EndpointPropertyType properties<1..*>;
TypedEndpointAddr endpoints<1..*>;
} ReqEndpointProp;
// Example
POST /endpointprop/lookup HTTP/1.1
Host: alto.example.com
Content-Length: 96
Content-Type: application/alto-endpointpropparams+json
Accept: application/alto-endpointprop+json,application/alto-error+json
{
"properties" : [ "pid", "example-prop" ],
"endpoints" : [ "ipv4:192.0.2.34", "ipv4:203.0.113.129" ]
}
//*************************************
// IR: endpoint properties
//*************************************
object {
VersionTag map-vtag; [DEPEND on properties]
EndpointPropertyMapData map;
} InfoResourceEndpointProperty;
object-map {
// OLD:
// EndpointProps [TypedEndpointAddr];
// ...
// A map object with each entry mapping
// a typed endpoint address to a epp object
TypedEndpointAddr -> EndpointProps;
} EndpointPropertyMapData;
object-map {
// JSONValue [EndpointPropertyType];
// ...
// A map object with each entry mapping
// a property type to a JSONValue
EndpointPropertyType -> JSONValue;
} EndpointProps;
// Example
HTTP/1.1 200 OK
Content-Length: 149
Content-Type: application/alto-endpointprop+json
{
"meta" : {},
"data": {
"map-vtag" : "1266506139",
"map" : {
"ipv4:192.0.2.34" : { "pid": "PID1", "example-prop": "1" },
"ipv4:203.0.113.129" : { "pid": "PID3" }
}
}
}
//*************************************
// --- Request for endpoint cost
//*************************************
object {
CostID cost-id; // must be among capabilities or default
JSONString constraints<0..*>; [OPTIONAL]
EndpointFilter endpoints;
} ReqEndpointCostMap;
object {
TypedEndpointAddr srcs<0..*>; [OPTIONAL]
TypedEndpointAddr dsts<1..*>;
} EndpointFilter;
// Example
POST /endpointcost/lookup HTTP/1.1
Host: alto.example.com
Content-Length: 195
Content-Type: application/alto-endpointcostparams+json
Accept: application/alto-endpointcost+json,application/alto-error+json
{
"cost-id" : {"mode":"ordinal", "type":"routingcost"},
"endpoints" : {
"srcs": [ "ipv4:192.0.2.2" ],
"dsts": [
"ipv4:192.0.2.89",
"ipv4:198.51.100.34",
"ipv4:203.0.113.45"
]
}
}
//*************************************
// -- IR: Endpoint Cost
//*************************************
object {
CostID cost-id;
EndpointCostMapData map;
} InfoResourceEndpointCostMap;
object-map {
//EndpointDstCosts [TypedEndpointAddr];
//...
// A map object with each entry mapping
// a typed endpoint address to a edc object
TypedEndpointAddr -> EndpointDstCosts;
} EndpointCostMapData;
object-map EndpointDstCosts {
//JSONValue [TypedEndpointAddr];
//...
TypedEndpointAddr -> JSONValue;
};
// Example
HTTP/1.1 200 OK
Content-Length: 231
Content-Type: application/alto-endpointcost+json
{
"meta" : {},
"data" : {
"cost-id" : {"mode":"ordinal", "type":"routingcost"},
"map" : {
"ipv4:192.0.2.2": {
"ipv4:192.0.2.89" : 1,
"ipv4:198.51.100.34" : 2,
"ipv4:203.0.113.45" : 3
}
}
}
}
_______________________________________________
alto mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/alto