Mike_Lowell_456
Sep 09, 2005Historic F5 Account
hash-based load balancing; aton() and pool member index's
Hi guys,
I've searched through the existing forum topics, and I couldn't seem to find an answer for this type of question.
My end goal is to distribute all traffic fairly evenly between two gateways, but ensure that a given client network (/24) always goes to the same gateway as long as the gateway is up (I only have two gateways). If one gateway goes down, I want to select the other gateway (i.e. send all traffic to the one gateway).
My idea for how to achieve this is as follows:
GATEWAY_INDEX = (CLIENT_IP_ADDRESS & 0xffffff00) % NUMBER_OF_ACTIVE_NODES
use pool "gateways" member GATEWAY_INDEX
This is "kind of" achievable, but I'm performing each step in a very inefficient manner that I think can be much better.
First, does anybody know a better way to convert an IP address to a number? So far I'm doing this:
regexp {(\d+)\.(\d+)\.(\d+)\.(\d)+} [IP::remote_addr] -> a b c d
set client_ip [expr [expr [expr $a << 24] + [expr $b << 16 ]] + [expr $c << 8]]
I was expecting to find a function like aton(), or a special format()/printf() format type, but I couldn't seem to find such a thing. Is there a better way to turn an IP address into a number? Also, notice that I'm intentionally only capturing the top 24 bits.
Next, I want to select pool members based on their index within a pool. i.e.
use pool mypool member index 0
..would select the first pool member, whereas:
use pool mypool member index 1
...would select the second pool member.
The goal being to generate a dynamic index into the pool based on how many members are available:
set active_member_count [active_members $pool_name]
So far I've worked around this by using specific server IP addresses starting at 1 that are in a row, such as 1.1.1.1 and 1.1.1.2.
My current rule looks like this:
when CLIENT_ACCEPTED {
regexp {(\d+)\.(\d+)\.(\d+)\.(\d)+} [IP::remote_addr] -> a b c d
set client_ip [expr [expr [expr $a << 24] + [expr $b << 16 ]] + [expr $c << 8]]
set gateway_network "10.10.1"
set pool_name "gate_pool"
set active_member_count [active_members $pool_name]
set gateway_hash [expr [expr $branch_client_ip % $active_member_count] + 1]
set gateway "$gateway_network.$gateway_hash"
pool $pool_name member $gateway
}
I do realize that much of this could be combined into a single step without variable assignements, but I've separated the individual steps for (some) additional clarity.
I'm not very good with TCL (as you can see!), so I think there must be a better way. Any help appreciated!
a1l0s2k9