Balance across LSN pools

When using CGNAT and multiple LSN pools are attached to a virtual server, BIG-Ip does not attempt to balance across the LSN pools. Balancing across LSN pools may be desirable in certain situations, such as where the pools correspond to different ISPs.

This iRule provides balancing across LSN pools, using an algorithm similar to CARP to statelessly persist clients to pools (this does not replace the persistence function of the LSN pools). The iRule contains documentation and offers debugging if needed. You must configure the names of the LSN pools correctly - if the configuration section contains invalid pool names, some connections will be terminated. If this happens an error with the invalid pool name will be logged in /var/log/ltm

 

# lsn-balance

# This iRule is intended to balance between two or more LSN pools, with 
# approximately equal use of all pools

# This uses an algorithm similar to CARP to persist clients to pools without
# using expensive "table" calls

when RULE_INIT {
    # Configures the names of the LSN pools
    set static::lsn_balance_pools {
        "/Common/LSN_split_1" 
        "/Common/LSN_split_2" 
        "/Common/LSN_split_3"
    }

    # Enable/disable debugging
    # 0 = disable, 1 = enable
    set static::lsn_balance_debug 0

    #####
    # No configuration past this point
    #####

    # Save an "llength" call per connection
    set static::lsn_balance_pool_count [llength $static::lsn_balance_pools]
}

when CLIENT_ACCEPTED {
    if {$static::lsn_balance_debug} {
        # More readable version with intermediate vars for debugging

        # Fetch the client IP
        set client_ip [IP::client_addr]

        # Derive the hash we'll use for pool selection from client IP
        set lsn_select_hash [fasthash $client_ip]

        # Choose the list index based on hash - hash modulo length of pool list
        set lsn_select_index [
            expr {$lsn_select_hash % $static::lsn_balance_pool_count}
        ]

        # Select pool from list of pools and use it
        set lsn_select_pool [lindex $static::lsn_balance_pools $lsn_select_index]
        
        # debug
        log local0. "lsn-balance: client: $client_ip pool: $lsn_select_pool hash: $lsn_select_hash index: $lsn_select_index"
        
        # Set pool selection
        LSN::pool $lsn_select_pool
    } else {
        # "one-line" version, equivalent to above
        # optimized by avoiding use of intermediate vars
        # but harder to read and offers no debugging

        LSN::pool [
            lindex $static::lsn_balance_pools [
                expr {
                    [fasthash [IP::client_addr]] % $static::lsn_balance_pool_count
                }
            ]
        ]
    }
}

 

Published Jul 11, 2024
Version 1.0

Was this article helpful?

No CommentsBe the first to comment