Forum Discussion
William_Benett1
Nimbostratus
Mar 28, 2007TCL capabilities in iRules
So i'm working on an iRule that will require me to do bitwise math in order to determine if the port number is odd or even. I believe I looked up the operator (&) but the iRuler gives me a syntax error when I attempt to save the iRule and upload it to my BIG-IP.
Can I use that operator? Is there a better method to determine if a number is odd or even (given the restrictions of iRules)?
- The bitwise AND operator "&" is supported. Could you post the segment of your iRule that is causing the problem? Likely it is something else in your assigment. You might need to wrap the math in an "expr" command.
http://tmml.sourceforge.net/doc/tcl/expr.html
Click herewhen HTTP_REQUEST { set port_is_odd [expr [TCP::local_port] & 1] if { $port_is_odd } { log local0. "Port [TCP::local_port] is odd" } else { log local0. "Port [TCP::local_port] is even" } }
- I haven't personally purchased any books on TCL for a reference, but relied on the online docs and TCL client distributions. Here are some links of interest.
- William_Benett1
Nimbostratus
Okay, so sides stepping the TCL knowledge stuff, I don't think I have a method to do what I want to do with my iRule.when RULE_INIT { set ::currentserver 1 } when CLIENT_ACCEPTED { switch -glob [TCP::local_port] { 49* { if {[TCP::local_port] > 49151 && 49250 > [TCP::local_port]} { if { [expr [TCP::local_port] & 1] } { odd port section: TCP::collect } else { even port section: use src based persistence only if {$::currentserver eq 1} { if {[LB::status node 10.10.4.150] eq "down"} { set ::currentserver 0 node 10.10.4.154 persist source_addr 300 } else { set ::currentserver 0 node 10.10.4.150 persist source_addr 300 } } else { if {[LB::status node 10.10.4.154] eq "down"} { set ::currentserver 1 node 10.10.4.150 persist source_addr 300 } else { set ::currentserver 1 node 10.10.4.154 persist source_addr 300 } } } } } default { discard } } } when LB_FAILED { if {$::currentserver eq 1} { if {[LB::status node 10.10.4.150] eq "down"} { set ::currentserver 0 set ::lbserver [session lookup source_addr [IP::client_addr]] log local0. "server $::lbserver" node 10.10.4.154 TCP::release } else { set ::currentserver 0 node 10.10.4.150 set ::lbserver [session lookup source_addr [IP::client_addr]] log local0. "server $::lbserver" TCP::release } } if {$::currentserver eq 0} { if {[LB::status node 10.10.4.154] eq "down"} { set ::currentserver 1 node 10.10.4.150 set ::lbserver [session lookup source_addr [IP::client_addr]] log local0. "server $::lbserver" TCP::release } else { set ::currentserver 1 node 10.10.4.154 set ::lbserver [session lookup source_addr [IP::client_addr]] log local0. "server $::lbserver" TCP::release } } }
- spark_86682Historic F5 AccountYou seem to have some round-robin login in the rule too. If I understand, the heart of the matter is:
when RULE_INIT { set ::minport 49151 set ::maxport 49250 } when LB_SELECTED { set lport [TCP::local_port] if { $lport > $::minport && $lport < $::maxport } { if { ! [expr { $lport & 1 }] } { even number port; 1st connection Persist on remoteIP:localport. Also, set up another persist entry for the odd number port connection coming next persist add uie "[IP::remote_addr]:$lport" 300 set lport [expr $lport + 1] persist add uie "[IP::remote_addr]:$lport" 300 } } } when CLIENT_ACCEPTED { set lport [TCP::local_port] if { $lport > $::minport && $lport < $::maxport } { if { [expr { $lport & 1}] } { odd number port; 2nd connection Persist on remoteIP:localport. Persist entry should already be there. if { [string length [persist lookup uie "[IP::remote_addr]:$lport"]] == 0 } { log "ERROR! Connection from [IP::remote_addr]:[TCP::remote_port] to [IP::local_addr]:[TCP::local_port] had no persist record!" reject } else { persist uie "[IP::remote_addr]:$lport" } } } }
- William_Benett1
Nimbostratus
First, thank you. The idea of prepping the persistence for the 2nd connection while we're doing the first is badass. I believe the problem i'm really running into is that was trying to avoid creating 100 different pools (one for each possible port), however i'm going to have to give up on that idea. I believe the interpreter is correctly telling me that I cannot set persistence for this connection because I'm not telling it to actually load balance anything. - William_Benett1
Nimbostratus
So i've been working with this and I can't seem to get information out of the persistence table. If I try and do a lookup during CLIENT_ACCEPTED it throws me a "Prerequisite operation not in progress" if I try and do it during LB_SELECTED I get nothing returned on my lookup. I can perform a lookup right after I set the persistence in LB_SELECTED, so i'm not sure why I can't do it again when the odd port connection comes in.when CLIENT_ACCEPTED { switch -glob [TCP::local_port] { 49* { if {[TCP::local_port] > 49151 && 49250 > [TCP::local_port]} { set lport [TCP::local_port] if { ! [expr {$lport & 1}]} { pool pool_$lport } else { set evenport [ expr $lport -1] set current [LB::server addr] set remaddr [IP::client_addr] set ourpool "pool_$evenport" set hoohaa [persist lookup source_addr [IP::client_addr]] log local0. "current: $current evenport: $evenport pers entry: $hoohaa remote_addr: $remaddr" } } } default { discard } } } when LB_SELECTED { if {[TCP::local_port] > 49151 && 49250 > [TCP::local_port]} { set lport [TCP::local_port] if { ! [expr {$lport &1}]} { even set remaddr [IP::client_addr] persist add source_addr [IP::client_addr] 300 set output [persist lookup source_addr [IP::client_addr] node ] log local0. "pers lookup: $output remip: [IP::remote_addr]" } else { odd set evenport [ expr $lport - 1 ] set current [LB::server addr] set remaddr [IP::client_addr] set ourpool "pool_$evenport" log local0. "pool: $ourpool remaddr: $remaddr" set hoohaa [persist lookup source_addr [IP::client_addr] ] log local0. "current: $current evenport: $evenport pers entry: $hoohaa remote_addr: $remaddr" if {[$entry != $current]} { LB::reselect pool pool_$lport } } } }
- William_Benett1
Nimbostratus
Heh, so I couldn't get the information out of the persistence table, as I described above. I do realize looking at this that I didn't quite follow through on Spark's idea. That said, I found a way to make it work. I initialized an array in RULE_INIT and then I store the load balancing decisions in that array, with the key being the client IP:socket pair. It works currently. If anyone is interested in this, let me know and I'll post a copy of it. - William_Benett1
Nimbostratus
Ah oops? I didn't think about clearing out the array, so I'll need to add in some code for the CLIENT_CLOSED event and I should be in good shape.
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