Forum Discussion

janholtz's avatar
janholtz
Icon for Altostratus rankAltostratus
Jul 28, 2010

New Radius Profile

Hi all

 

I am trying to create a simplified alternative -thanks to v10.x changes- to David Wang's super radius irule at:

 

http://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/149/Radius-Aware-Load-Balancing-via-iRules.aspx

 

 

What I am trying to achieve is detect only accounting start & stop messages, if we get one of these, they must be routed to one of 2 pool members depending on the modulo 2 value of the Frame IP address (don't ask).

 

If the message is an account stop, it must also delete the source based persistence entry for all other virtual servers. This entry should have the Frame-IP as the client IP.

 

Here's what I have at present:

 

-----------------------------------------------------------------------------------------

 

when CLIENT_ACCEPTED {

 

if { [UDP::payload length] > 4 } {

 

if {[RADIUS::code] == 4 } {

 

binary scan [RADIUS::avp 8] a* Frame_IP

 

binary scan [RADIUS::avp 40] H* statval

 

set Acc_Stat [expr 0x$statval]

 

if {$Acc_Stat == 1} {

 

binary scan [binary format c4 [split $fullval .]] H8 Hex

 

set decimal [expr 0x$Hex]

 

set modval [expr {$decimal % 2 }]

 

if { $modval == 0 } {

 

pool pool_radius member 1.1.1.1 1813

 

}

 

if { $modval == 1 } {

 

pool pool_radius member 1.1.1.1 1813

 

}

 

}

 

}

 

}

 

}

 

 

when LB_SELECTED {

 

if { $Acc_Stat == 2 } {

 

persist delete source "$Frame_IP any virtual"

 

}

 

}

 

-----------------------------------------------------------------------------------------

 

I have tried this code before, but we were not seeing the account stop messages come through correctly.

 

Would that be due to SOL11627 or is my code dodgy?

 

 

Regards

 

Jan

 

 

6 Replies

  • No Takers???

     

    Here's an optimised version that uses no variables (so I can enter the optimisation competition one day) :

     

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

    when CLIENT_ACCEPTED {

     

    if { [UDP::payload length] > 4 } {

     

    if {![catch [RADIUS::code]] equals 4 } {

     

    if {[expr 0x[binary scan [RADIUS::avp 40] H*]] == 1} {

     

    if { [expr {[expr 0x[binary format c4 [split [binary scan [RADIUS::avp 8] a*] .]] H8] % 2 }] == 0 } {

     

    pool pool_radius member 1.1.1.1 1813

     

    } else {

     

    pool pool_radius member 1.1.1.2 1813

     

    }

     

    }

     

    }

     

    }

     

    }

     

     

    when LB_SELECTED {

     

    if { [UDP::payload length] > 4 } {

     

    if {![catch [RADIUS::code]] equals 4 } {

     

    if {[expr 0x[binary scan [RADIUS::avp 40] H*]] == 2} {

     

    persist delete source "[binary scan [RADIUS::avp 8] a*] any virtual"

     

    }

     

    }

     

    }

     

    }

     

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

     

    Regards

     

    Jan

     

  • 20 lines or less??

     

    when CLIENT_ACCEPTED {

     

    if { [UDP::payload length] > 4 } {

     

    if {![catch [RADIUS::code]] equals 4 } {

     

    if {[expr 0x[binary scan [RADIUS::avp 40] H*]] == 1} {

     

    if { [expr {[expr 0x[binary format c4 [split [binary scan [RADIUS::avp 8] a*] .]] H8] % 2 }] == 0 } {

     

    pool pool_radius member 1.1.1.1 1813

     

    } else {

     

    pool pool_radius member 1.1.1.2 1813

     

    }}}}}

     

     

    when LB_SELECTED {

     

    if { [UDP::payload length] > 4 } {

     

    if {![catch [RADIUS::code]] equals 4 } {

     

    if {[expr 0x[binary scan [RADIUS::avp 40] H*]] == 2} {

     

    persist delete source "[binary scan [RADIUS::avp 8] a*] any virtual"

     

    }}}}

     

  • Hi Jan,

     

     

    Can you add debug logging before each command and provide a description and the logs for a failure?

     

     

    Thanks, Aaron
  • Also, this line can't ever be true. catch returns 0 if there was no error running the command and 1 if there was an error. Negating 0 or 1 will only result in 1 or 0.

     

     

    if {![catch [RADIUS::code]] equals 4 } {

     

     

     

    Maybe you want something like this to check if the RADIUS::code command runs without error and returns 4?

     

     

    if { ! [catch {RADIUS::code} result] and $result == 4 } {

     

     

    Aaron
  • Excellent catch, thank you Aaron! This is more a proposed rule than one already in place, I was just wondering if it seems sane and hopefully the people that developed the new Radius:: functionality can check if I am using their now code correctly (I've not seen any other rules using this new feature, and therefore am a bit skittish!) Best Regards Jan
  • Hi Jan,

     

     

    I haven't tested anything in the RADIUS namespace, so I couldn't tell you whether the rule functionally looks good or not. Maybe someone else can comment?

     

     

    Aaron