Description

This article explains how to perform unequal cost load balancing using only static routing.

Symptoms

The objective is to statically load balance traffic to optimize bandwidth utilization.



KB30740.jpg

The standard statically configured load balancing configuration is unaware of the bandwidth/link speed. Hence, it distributes the load evenly, which may not be desirable. In the figure shown above, we have three ISPs with speeds of 2Mbps, 4Mbps, and 6Mbps. We need to distribute the load across these three links to optimize bandwidth utilization.

Solution

By default, load balancing is disabled on J/SRX platforms. When two or more routes going to the same destination are present, the device will install only one route, usually the one with the best metric. The command to allow equal-cost load balancing is the following:

set policy-options policy-statement POLICY_NAME then load-balance per-packet

However, we can allow equal cost per flow load balance. See KB23417 - Equal-cost multipath support on SRX for flow-based forwarding [juniper.net]. SRX firewalls are stateful devices; they implement a "per-flow" load balance operation instead of a "per-packet" operation.

We will leverage the equal cost load-balance feature to achieve unequal cost load balance. The key is to generate multiple next-hops pointing to the same ISP next-hop in a desired ratio, such that when the device tries to do equal cost load-balancing, it ends up sharing the load in a ratio of the bandwidth. In the following example, we will configure unequal cost load balances for the default routes going to each ISP. This procedure should work for any route, if each route is going to the exact same subnet, having the exact same subnet mask.

Assume that the next hops for each ISPs are as follows:

  • ISP1 - 2Mbps: default-gateway IP: 10.10.10.1

  • ISP2 - 4Mbps: default-gateway IP: 172.16.10.1

  • ISP3 - 6Mbps: default-gateway IP: 192.168.10.1

In this example, we have three ISPs that have speeds of 2Mbps, 4Mbps, and 6Mbps, respectively. We can install two routes for the ISP that has 2Mbps, four routes for the ISP that has 4Mbps, and six routes for the ISP that has 6Mbps. This will allow a 2:4:6 distribution fashion. Since we are using pair numbers in this case, we could choose to compress it in a 1:2:3 fashion that would provide the same effect. However, in this example, for clarity we will be configuring the routes in a 2:4:6 fashion.

Note: IP addresses in the range 10.10.11.0/24, 10.10.12.0/24, 10.10.13.0/24 are not actual IP addresses; they are dummy IP addresses.

 

To configure unequal cost load balance, perform the following:

  1. Create and install dummy routes going to the next ISP's IP addresses:

set routing-options static route 10.10.11.1/32 next-hop 10.10.10.1
set routing-options static route 10.10.11.2/32 next-hop 10.10.10.1

set routing-options static route 10.10.12.1/32 next-hop 172.16.10.1
set routing-options static route 10.10.12.2/32 next-hop 172.16.10.1
set routing-options static route 10.10.12.3/32 next-hop 172.16.10.1
set routing-options static route 10.10.12.4/32 next-hop 172.16.10.1

set routing-options static route 10.10.13.1/32 next-hop 192.168.10.1
set routing-options static route 10.10.13.2/32 next-hop 192.168.10.1
set routing-options static route 10.10.13.3/32 next-hop 192.168.10.1
set routing-options static route 10.10.13.4/32 next-hop 192.168.10.1
set routing-options static route 10.10.13.5/32 next-hop 192.168.10.1
set routing-options static route 10.10.13.6/32 next-hop 192.168.10.1
  1. Install default static routes that will be going to the dummy IP addresses created in step 1.

set routing-options static route 0.0.0.0/0 next-hop 10.10.11.1
set routing-options static route 0.0.0.0/0 next-hop 10.10.11.2

set routing-options static route 0.0.0.0/0 next-hop 10.10.12.1
set routing-options static route 0.0.0.0/0 next-hop 10.10.12.2
set routing-options static route 0.0.0.0/0 next-hop 10.10.12.3
set routing-options static route 0.0.0.0/0 next-hop 10.10.12.4

set routing-options static route 0.0.0.0/0 next-hop 10.10.13.1
set routing-options static route 0.0.0.0/0 next-hop 10.10.13.2
set routing-options static route 0.0.0.0/0 next-hop 10.10.13.3
set routing-options static route 0.0.0.0/0 next-hop 10.10.13.4
set routing-options static route 0.0.0.0/0 next-hop 10.10.13.5
set routing-options static route 0.0.0.0/0 next-hop 10.10.13.6
  1. By default, the Juniper device will only do a route recursive resolution to find the outgoing interface. Therefore, adding the "resolve" keyword to the default route will allow the Juniper device to perform a second route lookup to find the outgoing interface.

set routing-options static route 0.0.0.0/0  resolve 
  1. Configure equal cost load balancing.

set policy-options policy-statement Load-Balance then load-balance per-packet
set routing-options forwarding-table export Load-Balance 

Verification

Since we are performing unequal cost load balancing, there are not many tools available to make sure that the packets are being forwarded in an unequal cost load balance fashion. However, you can test as shown here:

root@SRX> show route 

inet.0: 23 destinations, 23 routes (23 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0.0.0.0/0          *[Static/5] 00:00:58, metric2 0
                    >  to 10.10.10.1 via ge-0/0/0.0      << Note: The SRX device will 
                    >  to 10.10.10.1 via ge-0/0/0.0      install the route derived from 
                       to 172.16.10.1 via ge-0/0/1.0     the recursive routing lookup    
                       to 172.16.10.1 via ge-0/0/1.0     operation that the  
                       to 172.16.10.1 via ge-0/0/1.0     networking device will perform 
                       to 172.16.10.1 via ge-0/0/1.0     to find the outgoing interface.
                       to 192.168.10.1 via ge-0/0/2.0
                       to 192.168.10.1 via ge-0/0/2.0
                       to 192.168.10.1 via ge-0/0/2.0
                       to 192.168.10.1 via ge-0/0/2.0
                       to 192.168.10.1 via ge-0/0/2.0
                       to 192.168.10.1 via ge-0/0/2.0
10.10.10.0/30      *[Direct/0] 21:36:30
                    >  via ge-0/0/0.0
10.10.10.2/32      *[Local/0] 21:36:30
                       Local via ge-0/0/0.0
10.10.11.1/32      *[Static/5] 00:00:58
                    >  to 10.10.10.1 via ge-0/0/0.0      << Interface towards ISP 1.
10.10.11.2/32      *[Static/5] 00:00:58 
                    >  to 10.10.10.1 via ge-0/0/0.0
10.10.12.1/32      *[Static/5] 00:00:58
                    >  to 172.16.10.1 via ge-0/0/1.0     << Interface towards ISP 2.
10.10.12.2/32      *[Static/5] 00:00:58
                    >  to 172.16.10.1 via ge-0/0/1.0
10.10.12.3/32      *[Static/5] 00:00:58
                    >  to 172.16.10.1 via ge-0/0/1.0
10.10.12.4/32      *[Static/5] 00:00:58
                    >  to 172.16.10.1 via ge-0/0/1.0
10.10.13.1/32      *[Static/5] 00:00:58
                    >  to 192.168.10.1 via ge-0/0/2.0    << Interface towards ISP 3.
10.10.13.2/32      *[Static/5] 00:00:58
                    >  to 192.168.10.1 via ge-0/0/2.0
10.10.13.3/32      *[Static/5] 00:00:58
                    >  to 192.168.10.1 via ge-0/0/2.0
10.10.13.4/32      *[Static/5] 00:00:58
                    >  to 192.168.10.1 via ge-0/0/2.0
10.10.13.5/32      *[Static/5] 00:00:58
                    >  to 192.168.10.1 via ge-0/0/2.0
10.10.13.6/32      *[Static/5] 00:00:58
                    >  to 192.168.10.1 via ge-0/0/2.0

root@SRX> show route forwarding-table 
Routing table: default.inet
Internet:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
default            user     0                    ulst   262167     2
                                                 indr   262150     2
                              ab:45:27:a0:cd:23  ucst      574     6 ge-0/0/0.0 << Interface towards ISP 1.
                                                 indr   262156     2
                              ab:45:27:a0:cd:23  ucst      574     6 ge-0/0/0.0
                                                 indr   262157     2
                              cd:96:14:e8:fd:a3  ucst      580    10 ge-0/0/1.0 << Interface towards ISP 2.
                                                 indr   262158     2
                              cd:96:14:e8:fd:a3  ucst      580    10 ge-0/0/1.0
                                                 indr   262159     2
                              cd:96:14:e8:fd:a3  ucst      580    10 ge-0/0/1.0
                                                 indr   262160     2
                              cd:96:14:e8:fd:a3  ucst      580    10 ge-0/0/1.0
                                                 indr   262161     2
                              de:96:14:ea:60:3   ucst      575    14 ge-0/0/2.0 << Interface towards ISP 1.
                                                 indr   262162     2
                              de:96:14:ea:60:3   ucst      575    14 ge-0/0/2.0
                                                 indr   262163     2
                              de:96:14:ea:60:3   ucst      575    14 ge-0/0/2.0
                                                 indr   262164     2
                              de:96:14:ea:60:3   ucst      575    14 ge-0/0/2.0
                                                 indr   262165     2
                              de:96:14:ea:60:3   ucst      575    14 ge-0/0/2.0
                                                 indr   262166     2
                              de:96:14:ea:60:3   ucst      575    14 ge-0/0/2.0

root@SRX>show security flow session source-prefix 192.168.4.2

Session ID: 2754, Policy name: INSIDE_TO_ISP_1_POLICY/9, State: Active, Timeout: 296, Valid
  In: 192.168.4.2/49354 --> 91.216.63.240/80;tcp, If: reth5.4, Pkts: 2, Bytes: 92 
  Out: 91.216.63.240/80 --> 10.10.10.2/3427;tcp, If: ge-0/0/0.0, Pkts: 1, Bytes: 52

Session ID: 2802, Policy name: INSIDE_TO_ISP_1_POLICY/9, State: Active, Timeout: 1624, Valid
  In: 192.168.4.2/49226 --> 54.192.194.142/443;tcp, If: reth5.4, Pkts: 13, Bytes: 1228
  Out: 54.192.194.142/443 --> 10.10.10.2/2349;tcp, If: ge-0/0/0.0, Pkts: 13, Bytes: 8156

Session ID: 2916, Policy name: INSIDE_TO_ISP_2_POLICY/13, State: Active, Timeout: 1800, Valid  *See note below 
In: 192.168.4.2 /49268 --> 216.53.231.164/443;tcp, If: reth5.4, Pkts: 17, Bytes: 1384
Out: 216.58.219.164/443 --> 172.16.10.2/29294;tcp, If: ge-0/0/1.0 , Pkts: 15, Bytes: 5028

*Note: Traffic coming from the same source IP address should be going out from the different ISP's outbound interfaces. Also, there should be more flows going out from the ISP that we have assigned more ratio to (the one that has more bandwidth). In this case, there should be more flows exiting interface ge-0/0/2.0, which is the outside interface corresponding to ISP3.

Session ID: 2939, Policy name: INSIDE_TO_ISP_3_POLICY/15, State: Active, Timeout: 1800, Valid
  In: 192.168.4.2/49337 --> 31.13.73.36/443;tcp, If: reth5.4, Pkts: 117, Bytes: 6675
  Out: 31.13.73.36/443 --> 192.168.10.2/31513;tcp, If: ge-0/0/2.0, Pkts: 121, Bytes: 132803

Session ID: 2944, Policy name: INSIDE_TO_ISP_2_POLICY/13, State: Active, Timeout: 300, Valid
  In: 192.168.4.2/49374 --> 146.255.100.192/80;tcp, If: reth5.4, Pkts: 87, Bytes: 5452
  Out: 146.255.100.192/80 --> 172.16.10.2/17248;tcp, If: ge-0/0/1.0, Pkts: 85, Bytes: 123775

Session ID: 2945, Policy name: INSIDE_TO_ISP_3_POLICY/15, State: Active, Timeout: 1800, Valid
  In: 192.168.4.2/49238 --> 216.58.219.138/443;tcp, If: reth5.4, Pkts: 150, Bytes: 74339
  Out: 216.58.219.138/443 --> 192.168.10.2/7934;tcp, If: ge-0/0/2.0, Pkts: 114, Bytes: 66879

Session ID: 2954, Policy name: INSIDE_TO_ISP_3_POLICY/15, State: Active, Timeout: 1784, Valid
  In: 192.168.4.2/49243 --> 216.58.219.65/443;tcp, If: reth5.4, Pkts: 189, Bytes: 15038
  Out: 216.58.219.65/443 --> 192.168.10.2/15151;tcp, If: ge-0/0/2.0, Pkts: 198, Bytes: 180257

Session ID: 2955, Policy name: INSIDE_TO_ISP_1_POLICY/9, State: Active, Timeout: 2, Valid
  In: 192.168.4.2/58755 --> 8.8.4.4/53;udp, If: reth5.4, Pkts: 1, Bytes: 60
  Out: 8.8.4.4/53 --> 10.10.10.2/32603;udp, If: ge-0/0/0.0, Pkts: 1, Bytes: 129

Session ID: 2963, Policy name: INSIDE_TO_ISP_2_POLICY/13, State: Active, Timeout: 2, Valid
  In: 192.168.4.2/55217 --> 36.23.123.4/443;tcp, If: reth5.4, Pkts: 134, Bytes: 11114
  Out: 36.23.123.4/443 --> 172.16.10.2/14903;tcp, If: ge-0/0/1.0, Pkts: 134, Bytes: 10201

Session ID: 3078, Policy name: INSIDE_TO_ISP_3_POLICY/15, State: Active, Timeout: 1800, Valid
  In: 192.168.4.2/49340 --> 201.191.202.34/443;tcp, If: reth5.4, Pkts: 216, Bytes: 16246
  Out: 201.191.202.34/443 --> 192.168.10.2/15831;tcp, If: ge-0/0/2.0, Pkts: 187, Bytes: 251875

Session ID: 3172, Policy name: INSIDE_TO_ISP_3_POLICY/15, State: Active, Timeout: 300, Valid
  In: 192.168.4.2/49504 --> 23.14.180.21/80;tcp, If: reth5.4, Pkts: 5, Bytes: 721
  Out: 23.14.180.21/80 --> 192.168.10.2/19707;tcp, If: ge-0/0/2.0, Pkts: 4, Bytes: 2356

Modification History

2022-12-29: Archived
2023-02-13: Article re-published