Forum Discussion

Simon_Coffin_16's avatar
Simon_Coffin_16
Icon for Nimbostratus rankNimbostratus
Aug 20, 2014

iRule to load balance based on source IP

Hi Folks, This is my first attempt at an iRule so I wanted to bounce it off all of you for comment. There are, no doubt, syntax and logic errors.

The purpose of this iRule is to load balance based on the source IP address's third octet. If it's odd, then we go to pool member 1. If its even, to pool member 2. In this particular case, the session is ssl encrypted through the F5 so I cannot use a cookie or other persistence method. I am left with just the src and dest IP and an encrypted data packet to work with. Since the application requires some form of persistence, load balancing based on the IP address seems to be the best possibility.

when CLIENT_ACCEPTED { ! Use getfield to pull the source IP address's third octet and determine if its even or odd. set third-octet [expr {[getfield [IP::client_addr] "." 3]}] if { [$third-octet ends_with 0,2,4,6,8] { set destination even } elseif { set destination odd } }

! Send even sources to one Pool member, odds to the other.
if { [$destination eq odd] 
  pool Application-pool member server1 80
    persist source_addr 14400
  }
if { [$destination eq even]
  pool Application-pool member server2 80
    persist source_addr 14400
  }

!If a pool member is not available, send the session back to the Pool and set the persistence
!for a 60 minute timeout

when LB_FAILED { pool Application-pool persist source_addr 3600 LB::reselect }

There are a few things I'm not sure are going to work right, particularly the ends_with on line 4 to determine if the $third-octet is even or odd. I'm also not sure if I need the expr on line 3 when I'm setting the third-octet variable.

Many thanks in advance.

Simon Coffin

2 Replies

  • Let's try that again with better formatting.

    when CLIENT_ACCEPTED {
      ! Use getfield to pull the source IP address's third octet and determine if its
      ! even or odd.
      set third-octet [expr {[getfield [IP::client_addr] "." 3]}]
        if { [$third-octet ends_with 0,2,4,6,8]
          { set destination even }
        elseif
          { set destination odd }
    
      ! Send even sources to one Pool member, odds to the other.
    
      if { [$destination eq odd] 
        pool Application-pool member server1 80
        persist source_addr 14400
      }
      if { [$destination eq even]
        pool Application-pool member server2 80
        persist source_addr 14400
      }
    }
    
      !If a pool member is not available, send the session back to the Pool and
      !set the persistence for a 60 minute timeout
    
    when LB_FAILED {
      pool Application-pool
      persist source_addr 3600 LB::reselect 
    }
    
  • i understand pool member command won't create persistence record.

    e.g.

     config
    
    root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:80
        ip-protocol tcp
        mask 255.255.255.255
        pool foo
        profiles {
            http { }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        vs-index 68
    }
    root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm pool foo
    ltm pool foo {
        members {
            200.200.200.101:80 {
                address 200.200.200.101
            }
            200.200.200.111:80 {
                address 200.200.200.111
            }
        }
    }
    root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm rule qux
    ltm rule qux {
        when CLIENT_ACCEPTED {
      persist source_addr 14400
      pool foo member 200.200.200.101 80
    }
    }
    
     test
    
    [root@centos1 ~] curl -I http://172.28.24.10
    HTTP/1.1 200 OK
    Date: Thu, 21 Aug 2014 01:45:23 GMT
    Server: Apache/2.2.3 (CentOS)
    Last-Modified: Sun, 09 Feb 2014 08:39:51 GMT
    ETag: "41879c-59-2a9c23c0"
    Accept-Ranges: bytes
    Content-Length: 89
    Content-Type: text/html; charset=UTF-8
    
     persistence record
    
    root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) show ltm persistence persist-records
    Sys::Persistent Connections
    Total records returned: 0
    

    so, you may have to manually lookup and add persistence record in the irule.

    e.g.

     config
    
    root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm rule qux
    ltm rule qux {
        when CLIENT_ACCEPTED {
      if { [persist lookup source_addr [IP::client_addr]] ne "" } {
        persist source_addr 14400
      } else {
        pool foo member 200.200.200.101 80
      }
    }
    when SERVER_CONNECTED {
      persist add source_addr [IP::client_addr] 14400
    }
    when LB_FAILED {
      LB::reselect pool foo
    }
    }
    
     test
    
    [root@centos1 ~] curl -I http://172.28.24.10
    HTTP/1.1 200 OK
    Date: Thu, 21 Aug 2014 01:47:03 GMT
    Server: Apache/2.2.3 (CentOS)
    Last-Modified: Sun, 09 Feb 2014 08:39:51 GMT
    ETag: "41879c-59-2a9c23c0"
    Accept-Ranges: bytes
    Content-Length: 89
    Content-Type: text/html; charset=UTF-8
    
     persistence record
    
    root@(ve11a)(cfg-sync In Sync)(Active)(/Common)(tmos) show ltm persistence persist-records
    Sys::Persistent Connections
    source-address  172.28.24.1  172.28.24.10:80  200.200.200.101:80  (tmm: 0)
    source-address  172.28.24.1  172.28.24.10:80  200.200.200.101:80  (tmm: 1)
    Total records returned: 2