OpenBGPD and OpenOSPFD mini hackathon r2k6, report
contributions to various hackathons
[by Claudio Jeker] Over the last few years the OpenBSD project has created two more sub-projects: OpenBGPD and OpenOSPFD --two secure and efficient routing daemons for the BGP and OSPF protocol. Over the last two years OpenBGPD became a viable alternative to commercial and open-source BGP implementations. Together with OpenOSPFD it is possible to build OpenBSD based routers that can be deployed into the network infrastructure.
While most basic setup can be covered with an OpenBSD router running OpenBGPD and OpenOSPFD newer routing concepts like policy and multi-path routing and complex customer VPN setups are not supported. The kernel routing code is still based on 4.4BSD and lacks important features. Additional kernel support and features for the routing daemons are needed to cover these areas.
To accelerate the development process a mini-hackathon focused on routing support was hold from 14-18 June in Hamburg, Germany. five developers from Europe and one from Australia attended this hackathon.
The purpose of the r2k6 was to get the complex projects started and probably finish one task that was already half-way done. The focus was on the following three main projects:
- equal cost multi-path routing
- policy routing
- routing priorities
While there was already some multi-path code in OpenBSD it was not used because the final but most important bits were missing. Christopher Pascoe implemented these last bits during the r2k6. He made the code even a bit better. Instead of the simple modulo-n hash he implemented the hash-threshold mechanism to select paths based on source/destination IP address pairs. Additionally multipath routes are now inserted in the middle of the list of the multiple paths. This more complex mechanism to select and insert routes was chosen to keep the impact on flows in case of route changes small and follows the recommendations made in RFC2992.
Multi-path routing needs to be enabled via sysctl this safety barrier was added because having multiple paths to the same destination in the routing table may confuse user-land programs.
Henning Brauer took the lead in implementing policy routing. He implemented a way to have multiple routing tables concurrently in the network stack.
Additionally, with Hans Jörg Höxer he developed a way to tag packets via the pf(4) packet classifier. pf(4) adds a mbuf tag to each packet this tag can be used to chose the corresponding routing table. Currently it is only possible to tag packets but the necessary hooks to evaluate this tag have not yet been addedto code. During the implementation some problems where identified resulting in a couple of interesting discussion rounds.
When using multiple routing tables one issue is where to store Layer 2 addresses. Arp entries are stored as host routes in the routing table. With multiple tables it is possible to either use the main routing table for these link-local addresses or adding them to each routing table on demand. Using the main table is easy to implement --no hooks in the link layer specific code is needed-- but this has some drawbacks. It is not possible to have the same IP in two or more routing tables with different link-local address. This is needed to support multiple VPN on one system. So we decided that every routing table instance needs its one link-layer information. A result of this decision is that ifconfig(8) needs a way to know into which table a interface needs to be added. Another issue was how to access these additional tables via the routing socket. By default multiple tables should not be visible to a listener --a socket option is needed to enable reception of these additional messages. This is the only way of implementing multiple tables without causing compatibility issues.
Claudi Jeker started with the third big project --routing priorities. The idea of routing priorities is that each user-land routing daemon has a specific priority. It is possible to have the same prefix multiple times in the kernel routing tables each version at a different priority. The kernel chooses the most preferred version to forward packets. This simplifies the user-land daemons because they nolonger need to keep track of changes done by other daemons.
Again there are backwards compatibility issues. Many ideas were discussed starting from adding a second routing socket with a new API or adding new messages to the existing socket. The conclusion was that the new features should not result in massive changes to the API.
As an example the multipath code uses a special Flag to specify additional routes and so user-land apps are able to ignore them. A similar method is used for routing priorities, only changes made to the active priority are sent to the routing socket. If a lower priority route is modified no route message will be sent to all routing socket listeners. This way, user-land apps do not need to track the priorities.
A general conclusion found during this event is that the current routing socket misses some features. It is not possible to filter messages and receive only specific messages. Especially daemons like dhcpd and dhclient which listen on the routing socket only to track interface state changes could benefit from such a filter. It is not easy possible to extend the messages or the protocol. So adding new features is not easy. A consensus was found that new features should be implemented with minimal changes to the API. A complete reimplementation of the routing socket is currently not considered the current code should handle all current needs.