Forum Discussion
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
- Mike_Lowell_456Historic F5 AccountOne correction, the client network address needs to be shifted right 8 bits before the modulus is computed, which is not done in the pseudo-code, or the example iRule...the example above could never work as expected with such a small modulus. Whoops!
- JRahm
Admin
If you use least connections on your gateway pool and build a child profile to the srcaddr persistence profile with a mask of /24, you shouldn't need an iRule at all to achieve your goals. If one gateway that has persistent records goes down, the persistent information is deleted and new connections will flow to your only available gateway.when CLIENT_ACCEPTED { use pool gate_pool persist srcaddr mask 255.255.255.0 }
- Mike_Lowell_456Historic F5 AccountThanks!
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects