The Internet is controlled by a single protocol: BGP. This protocol has proven to be robust, fast and extremely scalable. It is not ideal, though, since it only provides a way of exchanging prefixes between peers, without any regard to how network managers would like the actual traffic to be distributed over our links.
Typical problem: most of my outbound traffic goes out via T1, while most of my inbound traffic comes in via T2
Half of the problem is easy to solve
Controlling the ‘outbound’ traffic is pretty easy – either with some smart scripting or using specialized optimization solutions. Either way, controlling the outbound traffic from my AS is no big concern. The real problem appears when it comes to controlling the *inbound* traffic. How do I force my peers to send me traffic the way I would like? Some techniques do exist: applying AS-Prepends to what I announce, tagging my BGP choosing not to announce some of my prefixes to some of my neighbours. All these however require application of tricky logic, constant supervision and never-ending maintenance.
There is also LISP, a protocol created from the ground up with the exact purpose of solving most of the modern Internet issues. LISP is, however, a complex protocol that requires new infrastructure to be deployed (MAP servers, LISP-aware routers etc). One of the biggest complications with LISP is that it relies on tunnelling for controlling the path that packets should be sent over.
Is tunneling really necessary?
Nowadays, the Internet is a very, very meshed network. Everybody peers with everybody, not only at the top level, but even leaf ASs often have many direct peerings with a variety of neighbours, or at the very least a few Tier-1 transit providers. During our research, we noticed that an AS equipped with several transit services often has sufficient path diversity to select an acceptable outbound path towards almost any destination.
In the above example we see that AS1 can choose multiple paths to AS2, and some of them will end up on different inbound points on the AS2 side. This means that if AS2 had some way to tell AS1 ‘please do your best to send me packets over my T2 peering’, AS1 could make it happen.
That’s where RPP comes into play
RPP stands for ‘Routing Preference Protocol’. RPP is a very simple protocol that allows Autonomous Systems to communicate inbound routing preferences to each other.
RPP is a protocol that allows users to exchange routing ‘preferences’ between ASs. First of all, the AS needs to have a routing controller. After all, if you are fiddling with routing, most likely you have a dedicated machine for that. The controller is the one that will exchange RPP preferences with remote ASs.
How to locate the routing controller for a given prefix
When a routing controller wishes to locate a remote controller responsible for a given prefix, it must perform a reverse DNS lookup for a TXT entry of the prefix’ IP address. This should return an entry of the format “RDE:IP_ADDRESS”, where “IP_ADDRESS” must be either an IPv4 or an IPv6 address of the routing controller.
Querying a Routing Controller
A routing controller accepts external queries using the Routing Preferences Protocol (RPP). RPP is a 7bit text, TCP-based protocol. Routing Controllers listen on port TCP/4343. The protocol is always behaving as follows: the client connects to server (SYN/SYN-ACK/ACK) • client sends a request terminated with a CR/LF terminator • server answers • both server and client close the connection
The list below presents all queries that a Routing Controller must answer to (to date, only one is available: SETINPREF). Every query is a single line, and MUST be terminated with a CR/LF line terminator. The query is always composed of a command, followed either by the CR/LF line terminator if no parameters are provided, or followed by a space followed by a list of tab-separated parameters. Parameters themselves can be organised in lists – these are space-separated.
The SETINPREF query indicates to the Routing Controller the routing preference regarding traffic it sends to dstlist, where dstlist is a list of unique, non-colliding prefixes. Each prefix is written in CIDR notation. Prefixes are separated from each other with a single space (ASCII 0x20). When the controller will send traffic to one of the destinations in the dstlist, it should follow these preferences, as long as it doesn’t collide with its own internal policies. This preference should be applied as long as the TTL (in seconds) hasn’t expired.
The AS list is a list of AS:weight pairs, where pairs are separated with a single space from each other. The “AS” part is the AS number of the autonomous system that the remote AS peers with. The weight is the preference for each AS entry point. The weight’s value must be in the range 0..255. A higher value means a higher inbound preference. When the remote Routing Controller does not have any preference, it should set the value to 127. A higher value indicates that the remote correspondent wishes to receive traffic via this AS peering, while a lower value indicates that it would prefer NOT to receive traffic via this AS.
The Routing Controller that receives a preference is expected to analyse the available AS-PATHs it knows for the remote destination, and try to choose one that reflects the destinations wish.
It’s worth noting that accepting any re-routing requests from the external world comes with its share of risks. This is why any implementation should perform a quick “authentication” of all RPP requests it receives. For every prefix that the RPP query contains, the RPP controller should discover the responsible remote controller, and make sure that the request is indeed originating from the very same IP address.
Second, IP address providers should avoid delegating the first leaf prefix of their supernet, since the RPP controller records would collide (typically, if your prefix is 198.18.0.0/16 and you are delegating /24 prefixes to your customers, then you should make sure that you retain control over 198.18.0.0/24, or at least that you do not allow the customer to create any RPP record for this prefix).
Looking for some actual code? We have uploaded to GitHub a simple tool that makes it possible to perform a controller lookup for a given prefix and feed a remote controller with routing preferences. See our GitHub project.