Using Policy-Based Routing to Route Based on Source Address

Using Policy-Based Routing to Route Based on Source Address

Problem

You want to use different network links depending on the source address.

Solution

Policy-based routing allows you to configure special routing rules beyond the normal IP routing table. One common application is to route packets based on the IP source address rather than the destination address:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#access-list 1 permit 10.15.35.0 0.0.0.255
Router(config)#access-list 2 permit 10.15.36.0 0.0.0.255
Router(config)#interface Ethernet0
Router(config-if)#ip address 10.15.22.7 255.255.255.0
Router(config-if)#ip policy route-map Engineers
Router(config-if)#ip route-cache policy
Router(config-if)#exit
Router(config)#route-map Engineers permit 10
Router(config-route-map)#match ip address 1
Router(config-route-map)#set ip next-hop 10.15.27.1
Router(config-route-map)#exit
Router(config)#route-map Engineers permit 20
Router(config-route-map)#match ip address 2
Router(config-route-map)#set interface Ethernet1
Router(config-route-map)#end
Router#

Discussion

This configuration example defines a special routing policy for a group of users defined by the route map called "Engineers." This name is arbitrary, and we recommend that you choose names for your route maps that are meaningful in your organization. This example applies the route map to all of the packets received on the interface Ethernet0. This might be required because these users need to use a special higher capacity link, for example.

There are two clauses in this route-map. The numbers 10 and 20 at the end of each of the route-map command lines are used to specify the order that the router will apply these clauses when making routing decisions. It is a good practice to use widely spaced numbers like this to make it easier to insert new clauses between them. For example, if we needed to add a new clause that had to be executed after the first one, but before the last one, we could give it a value of 15.

It is also important to remember that every route map ends with an implicit deny all. This means that the packets that don't match either of the clauses in this route map will be unaffected, and will use the standard IP routing table.

The permit field is somewhat confusing in general because it governs whether the route map clause will permit or deny the set operation contained below it. There are very few cases when the deny option is used in practice.

The first route-map clause takes action based on the match command:

Router(config)#route-map Engineers permit 10
Router(config-route-map)#match ip address 1
Router(config-route-map)#set ip next-hop 10.15.27.1
Router(config-route-map)#exit

This command compares the contents of the IP header with what is defined in access-list number 1. Note that this is a standard access-list, which is used only to match the source address in the IP header. You can also use extended access-lists to match any of the header contents. With extended access lists, you can even match TCP or UDP port numbers. The term address in the route-map match clause is slightly misleading when extended access-lists are used because you can actually match just about anything in the IP header. However, in this case we do happen to be looking for an address.

Access-list 1 will match any packet with a source address in the range from 10.15.35.0 to 10.15.35.255:

Router(config)#access-list 1 permit 10.15.35.0 0.0.0.255

If the match is successful, the route-map will then apply the set command, which overrides any routing table information and sends the packet to the next-hop router, 10.15.27.1. Note that this next-hop router must be on a directly connected network because the router will bypass its routing table when it forwards these packets. If the next hop address is not part of a directly connected subnet, the router can't route the packet because it has already bypassed the routing table in its decision process.

The second clause works in a similar way, but matches with a different access-list and sets a different next-hop value:

Router(config)#route-map Engineers permit 20
Router(config-route-map)#match ip address 2
Router(config-route-map)#set interface Ethernet1

This clause also handles the routing differently. Instead of specifying a next-hop, it specifies that any packets matching this rule will be forwarded directly out the interface Ethernet1. This means that either the destination device must be on this segment, or there must be a router configured with Proxy ARP that can forward the packet to the ultimate destination.

Because the route map ends with an implicit deny all, any packets that don't match any clause are routed in the normal way using information in the routing table.

You can use the set next-hop command to set a series of possible next-hops:

Router(config-route-map)#set ip next-hop 10.15.27.1 10.15.37.1

And you can also specify several different possible interfaces:

Router(config-route-map)#set interface Ethernet1 Ethernet2

This allows you to define what to do if there is no way to route to one of these next-hop devices. If the first address, or the first interface, is not available, the router will use the second.

The router will consult its routing table to decide whether the specified next-hop router or interface is available. This is important because in many cases, such as Ethernet segments, it is possible to lose contact with the next-hop router, but not lose the routing table entry. In this case, the packet will simply be dropped.

In IOS version 12.0(3)T and later, there is a partial solution to this problem. You can specify the set ip next-hop verify-availability command to make the router use CDP to test whether the next-hop device is up:

Router(config)#route-map Engineers permit 10
Router(config-route-map)#match ip address 1
Router(config-route-map)#set ip next-hop 10.15.27.1
Router(config-route-map)#set ip next-hop verify-availability

Since this uses CDP, you have to ensure the CDP is enabled on the interface that leads to this next-hop device, and that device also has to be running CDP (meaning it must be another Cisco router). This is not a perfect solution because not all media types support CDP, and because it can cause performance problems. Furthermore, CDP uses a relatively long timeout period by default (180 seconds), so it is slow to respond to failures.

If none of the next-hops is available, the router will simply use its normal routing table. If the routing table does not have an entry for this route, you may want to specify a different default than the router's general default gateway:

Router(config)#route-map Engineers permit 10
Router(config-route-map)#set ip default next-hop 10.15.47.1

You can also specify a default interface in a similar way:

Router(config)#route-map Engineers permit 10
Router(config-route-map)#set default interface Null0

In this case, the default interface is the Null0 interface. Setting this will force the router to discard the packets rather than use the router's general default gateway.

There is one other extremely important command in the main recipe example, ip route-cache policy:

Router(config)#interface Ethernet0
Router(config-if)#ip route-cache policy

This command tells the router to use fast switching rather than process switching when processing policy commands on this interface. This command is new with IOS Version 12.0. Without it, all policy processing is handled by the router's CPU. This can cause serious performance problems in a slower router, or if the traffic load is heavy.

Note, however, that not all Policy-Based Routing commands can be fast-switched. In particular, the set ip default next-hop and set default interface commands are not supported. Furthermore, Fast Switching has only limited support for the set interface command. In particular, the destination interface must have route-caching enabled, or it must be a point-to-point link. And even if these conditions are true, the router still must check its routing table to ensure that the destination interface is valid, and this happens at the process level. Recipe 5.7 discusses these commands.

It is important to remember that because policy-based routing overrides the normal routing tables within the router, it can result in some interesting and confusing troubleshooting problems. In the example above, if the next-hop value, 10.15.27.1 suffers a failure but its subnet doesn't drop out of the routing table, then there is no dynamic routing protocol involved to find a new path. Worse still, when you try to diagnose the problem, normal procedures like trying to ping from the router to the required destination, will give unpredictable results because the ICMP packets originating on the router will not be subject to the routing policy. So you may find that you can ping, but that the application doesn't work for certain users.

For this reason, we recommend avoiding policy-based routing unless there is no other way to accomplish the required goals.

See Also