sre_81614
May 06, 2009Nimbostratus
My iRule Impressions & Optimiziation-Request-"Contest" (IP to STOREID)
Hello community,
first of all I have to say two 4 words: I love our BIGIPs! :-)
But when it comes to "iRule-Scripting", I see some disadvantages not regarding tcl itself, but the implementation of tcl in LTM which brings some limitations with it. (documented here: https://support.f5.com/kb/en-us/solutions/public/6000/300/sol6319.html ). For Example, this disallows "iRulers" like me from using user defined procedures (using the proc command). This is the biggest disadvantage compared to "native" tcl scripting, because you have to write down the same function every time you need it in your script. I know there are already discussions (for example at http://devcentral.f5.com/Default.aspx?tabid=53&forumid=5&tpage=1&view=topic&postid=2156428332 ) and also Customer Requests (CR96170) asking F5 to allow the proc command! I've also contacted our F5 representive refering to this request. Not documented - but also unusable/non-functional - are some math commands like "pow"! ^^
Said that, let me talk about my real matter of concern, and why I opened this thread.
I'm working at a retail company in Germany, which got 1400 stores/branchoffices connected to our headquarter. These stores are using webapplications (let's call it the store-intranet) hosted at our headquarter. All this stores, got a unique IP address, which can be calculated on a static algorithm. In the past, the webapplication server knew this algorithm to identfiy the store id by the client ip address or X-Forwarded-For Header including the client ip address. That means that all applications (some written by our own developers, some written by 3rd parties) always had to know the algorithm to calculate the store id based on the ip to enforce permissions/views for the specific store requesting a page/element!
Now, having our lovely BIGIPs, we moved this "ip2storeid"-functionality into the loadbalancer (using iRules!), so modifications on this algorithm only have to be done on one central place. This saves a lot of time and prevent implementation errors on the application(server)side. Simply said, the loadbalancer takes the ip, calculates the storeid based on the given algorithm and inserts a X-Store-Id in to the request header before sending it to the application servers. Works like a charme!
BUT! (there's always a but :-))... After evualating the iRule perfomance, it shows up that this algorithm takes "a few" more cpu cycles! This part of the iRule takes an 450000cycles/request average!!
So I'd like to ask all you "iRulers" out there to take a little challenge on my script, to save cpu cycles ! (but obtain all functionality and errorhandling as already implemented!)... Because of.. ME == networkenginer-by-heart && ME != programmer-by-heart I guess there is a lot of potential, to save cpu cycles in this part of my I rule.
'Nuff said, here's the part of my iRule I've talked (too much!?) about:
Set X-VKST-ID
set ip [IP::client_addr]
Setting the ip for testing purposes because dev workstation does not belong to store-network ;-)
set ip 10.192.18.0
if {[scan $ip "%d.%d.%d.%d" a b c d] == 4} {
foreach i "$a $b $c $d" {
if {($i > 255) || ($i < 0)} {
return ""
}
}
set iplong [expr {$a} << 24 | {$b} << 16 | {$c} << 8 | {$d}]
if {$iplong < 0} {
set iplong [expr 4294967296 + {$iplong}]
}
}
set net_start 172.20.0.0
if {[scan $net_start "%d.%d.%d.%d" a b c d] == 4} {
foreach i "$a $b $c $d" {
if {($i > 255) || ($i < 0)} {
return ""
}
}
set net_startlong [expr {$a} << 24 | {$b} << 16 | {$c} << 8 | {$d}]
if {$net_startlong < 0} {
set net_startlong [expr 4294967296 + {$net_startlong}]
}
}
log local0. "net_startlong1 is $net_startlong"
set net_size 262144
set net_segment_size 32
if { $iplong >= $net_startlong && $iplong < ( $net_startlong + $net_size ) } then {
log local0. "netversion 1 found."
set VKSTID [expr ( {$iplong} - {$net_startlong} ) / {$net_segment_size} ]
if {[HTTP::header exists X-Store-id]} {
HTTP::header replace X-Store-Id $VKSTID
} else {
HTTP::header insert X-Store-Id $VKSTID
}
}
set net_start 10.192.0.0
if {[scan $net_start "%d.%d.%d.%d" a b c d] == 4} {
foreach i "$a $b $c $d" {
if {($i > 255) || ($i < 0)} {
return ""
}
}
set net_startlong [expr {$a} << 24 | {$b} << 16 | {$c} << 8 | {$d}]
if {$net_startlong < 0} {
set net_startlong [expr 4294967296 + {$net_startlong}]
}
}
log local0. "net_startlong2 is $net_startlong"
set net_size 4194304
set net_segment_size 512
if { $iplong >= $net_startlong && $iplong < ( $net_startlong + $net_size ) } then {
log local0. "netversion 2 found."
set VKSTID [expr ( {$iplong} - {$net_startlong} ) / {$net_segment_size} ]
if {[HTTP::header exists X-Store-id]} {
HTTP::header replace X-Store-Id $VKSTID
} else {
HTTP::header insert X-Store-Id $VKSTID
}
}
The intention for you to help me on this is easy! Save cpu cycles = save power consumption = save planet earth! Long live the green IT! :-)