The routing logic in the Firebrick operates mostly using a conventional routing system of most specific prefix. This means that at any one time there may be many routes in place, and they may cover any prefix. A routing rule simply defines where to send traffic for addresses in the prefix specified. A prefix is a block of IP addresses using a net mask, which creates a power of two number of IP addresses.
A prefix is defined as an IP address and number of bits in the prefix in CIDR notation. e.g. 2001:db8::/32 or 192.168.0.0/24.
Conventional routing simply means that each route covers a prefix and where/how to send the packet. The routing rule that is used for any packet is the most specific prefix that applies based on the destination IP of the packet - i.e. the prefix with the smallest block covering the target IP address. Conventional routing is done using the target IP address only, and applies as each packet is processed.
This means if you have a route for 10.0.0.0/8 to one place and a route for 10.0.1.16/27 to another, then an IP for 10.0.1.17 will use the latter, smaller, route.
The order in which routes are created does not normally matter as you do not usually have two routes that are the same prefix. However, there is an aspect of every route called the localpref which decides between identical routes - the higher localpref being which applies. If you have identical routes with the same locapref then one will apply (you cannot rely on which one) but it can, in some cases, mean you are bonding multiple links (see below).
You can show the routes that apply for a specific destination IP address using the command line.
Routing rules can specify various different types of routing.
Whenever you define a subnet or one is created (e.g. by DHCP) you are creating a route for the IP prefix that is the subnet. This is a route to send that traffic to an Ethernet interface. This is the whole point of defining a subnet. Traffic to the subnet will use ARP or ND to find the final MAC address to send the packet (with the exception of the last IP in an IPv4 subnet which is broadcast).
In addition, a subnet definition creates a very specific single IP route for the IP of the FireBrick as defined in the subnet. This is a separate route which is to send traffic to the FireBrick itself.
A subnet can also have a gateway specified, either in the config or by DHCP or RA. This gateway is just like creating a route to 0.0.0.0/0 or ::/0 as a specific route configuration. It is mainly associated with the subnet for convenience. If defined by DHCP or RA then, like the rest of the routes created by DHCP or RA, it is removed when the DHCP or RA times out.
Example: <subnet ip="192.168.0.1/24"/> creates a route for 192.168.0.0/24 to the port group and VLAN for the <interface.../> that encloses the subnet, and a loopback route for 192.168.0.1 as the FireBrick's own IP.
Routes can be defined to send traffic to another IP address. This is valid if that does not create a loop, obviously. When a route is to an IP, the target IP in the routing rule is then looked up, recursively, to find the real destination.
Example: <route ip="0.0.0.0/0" gateway="192.168.0.100"/> creates a default route for IPv4 traffic to 192.168.0.100. The routing for 192.168.0.100 has to be looked up to find the final target, e.g. it may be to an Ethernet interface where an ARP is done for 192.168.0.100 to find the MAC to send the traffic.
The way routing loops are handled depends on how the route is created. Normally a route that loops causes traffic to the route to be dropped. However, in the case of BGP, any route that is infeasible (i.e. because it is a loop) is ignored, allowing other routes (larger prefixes or lower localprefs) to apply instead, and also causing the infeasible route not to be propagated to peers.
There are routing objects for blackhole and nowhere which define prefixes which are routed to a black hole (packets dropped) or nowhere (icmp error) respectively. When using BGP you can also define a network which is announced but not actually routed.
The routing rules also allow routing IPv6 traffic via IPv4 tunnels (IP protocol 41). This is done simply by making a routing rule for an IPv6 prefix with an IPv4 target address, or a target address that is in 2002::/16. The result is the traffic is wrapped up in an IPv4 protocol 41 header and sent to the IPv4 address.
Example: <route ip="::/0" gateway="126.96.36.199"/> creates a default IPv6 route to send traffic wrapped as 6in4 to 188.8.131.52
Apart from defining routes in the configuration you can use BGP or possibly other routing protocols to have routes added and removed. Routing protocols usually create a route that is to an IP address, and this is looked up recursively to find the final destination. Loops in the definition can cause the route to be considered invalid and not be used.
Bonding is more generally described in the bonding section. Bonding is only available if you have a FireBrick that supports it, such as a fully loaded FB2500 or FB2700.
Basically, bonding means that when you have defined two or more routes that could equally apply, then packets are spread out between the routes based on speed controls you have set. It only applies where there is nothing to decide between the routes, so same prefix, and localpref. It has the to be the best localpref else the better one applies. If there is a more specific prefix then that applies instead, as normal. It also only works for certain types of route (configured route to ip, route to pppoe, route to L2TP session or route to FB105 tunnels.
Speed controls can be applied to various types of routes. This can be by a speed="..." attribute or setting a graph which has a speed defined using the <shaper.../> config to set the speed of the graph. Traffic via such routes has the speed limited to that which is set. However, in the case of bonding the speeds of the routes over which there is a choice are used to balance the amount of traffic sent via each route. Where you want to bond routes but not limit the speed you can set speeds higher than you need.
Where you have identical routing rules that are to Ethernet interfaces, then bonding makes no sense. In this case the FireBrick will initially try an ARP or ND to all of the valid Ethernet interfaces. If it gets a reply it then prefers that specific Ethernet interface (until the ARP/ND stops working). Just like bonding this applies only where the routing rule is otherwise identical. This feature works even on FireBricks that do not have bonding.
The result of this is that you can have the same subnet on more than one Ethernet interface, and the FireBrick works out which addresses are on which interface. In such cases you often want devices one one interface to see devices on the other via the FireBrick. To achieve this you need to set proxy-arp="true" in all of the subnet definitions. This causes the FireBrick to try an ARP or ND on the other subnets when it sees one, and if it gets a reply it will send a proxy ARP or ND reply on the subnet that was asking. This allows the FireBrick to bridge the subnets for unicast traffic, and allows that to be subject to any firewalling rules.
Routes can be defined using a profile on the config, or associated with something that has a state like L2TP, FB105, or PPP links. When the link is down or the profile if off then the related routes are removed. This does not apply to subnets when the interface goes down.
This can be useful where a specific interface such as PPPoE is defined with one localpref, and then a separate route is defined with a lower localpref as a fallback route if the PPPoE link drops.
Routes can be defined in the config in a number of ways:-
Note that ip-groups cannot be used when defining subnets or routes. IP-groups allow arbitrary ranges and not just prefixes. Routes can only use prefixes. However, route-overrides (see below) can use ip-groups.
All of the above logic operates within a numbered routing table, the default being 0 (zero). The various ways to add routes allow the routing table to be defined, and so allow completely independent routing for different routing tables. Each interface (port group and VLAN) is logically in a routing table and traffic arriving on it is processed based on the routes in that routing table. Tunnels like fb105 and l2tp allow the wrapped tunnel to work on one routing table and the payload to be on another. The only way to jump between routing tables is to use route overrides on firewalling models.
All of the above defines a conventional routing logic with addition of some handling for bonding and duplicate subnets. Otherwise it operates very much like any conventional router. However the FireBrick allows the possibility of route overrides which control routing in more more detail. This feature is part of the session tracking in firewalling models and is described in more detail in the firewall section.
Basically, when establishing a session it is possible to scan an ordered list of rules which can consider not only the target IP but also source IP, protocol, ports, and interfaces being used. The result is to set a new routing target IP for the session (and possibly a routing table to jump tables). This is done for each direction on the session and remembered. This new target IP is then used on a per packet basis in the same way as above instead of the target IP of the packet.
Because the route-override just sets a new target routing IP and does not allow you to set a specific tunnel or such, you may want to have a dummy single IP addresses routed down a tunnel, and then use route-override rules to tell specific sessions to use that IP as the gateway. Future releases may provide a means to specify a tunnel as a routing gateway more directly.