Forum Discussion

Nathan_McMahon_'s avatar
Nathan_McMahon_
Historic F5 Account
May 05, 2005

Direct requests based on hashed cookie data

I have a requirement to pull a numerical value from a cookie and direct the request to one of 12 pools based on the hashed value of that cookie data. For example, a client's cookie contains 62. Dividing by 12 leaves a remainder of 2, so the request would be sent to pool_2. The idea is that the each of the server pools would then only need to cache 1/12 of the total sum of the application data. The initial cookie generation is in place today, with Apache proxies to perform this persistence mechanism. I'm hoping to remove the extra layer of Apache proxies with this rule.

 
 when HTTP_REQUEST {  
     set CookieId [HTTP::cookie User_cookie] 
     set TempCookieId [expr $CookieId / 12.0] 
     set TempCookieId2 [expr floor $TempCookieId] 
     set NewCookieId [expr 12 * ($TempCookieId - $TempCookieId2)] 
      then send the connection to pool $NewCookieId 
 }

I'm running into a number of problems, mostly centered around string to integer or floating point. Using 12 instead of 12.0 doesn't error out, but my attempt at logic is to capture the remainder. Using the 12.0 I find %g via the logs. Also, I'm not sure what the best workaround is in place of the floor command (dropping off everything after the decimal point, perhaps findstr?) as it seems this is an unsupported command.

Is there a better way to generate this hash mechanism, am I close to being on the right track? Any suggestions are greatly appreciated in advance.

Nathan
  • rapmaster_c_127's avatar
    rapmaster_c_127
    Historic F5 Account
    What does your cookie data look like? Any particular reason you're using floor and divides instead of modular division? (The % operator.)

     

     

    We don't allow floating-point in iRules, since tmm is essentially the kernel. However, you should be able to use a simple modular division to accomplish what you need. If the contents of the cookie isn't evenly entropic enough, you could always CRC32/MD5/SHA1 it and then perform your modular division on the hashed/digested value.
  • Aren't you just looking for the modulus operator? If all you want is the remainder from the first number divided by the second, you could just use the % operator. In your example, 62 % 12 would return 2. Here's an iRule as a reference.

     

     

    when HTTP_REQUEST { 
       set CookieId [HTTP::cookie User_cookie]  
       if { [string is integer $CookieId] } { 
         set PoolId [expr $CookieId % 12 ] 
         set PoolName "Pool_$PoolId"  
          pool $PoolName 
         log "cookieid_rule: CookieId = $CookieId; PoolId = $PoolId; PoolName = $PoolName" 
       } else { 
         log "cookieid_rule: Invalid CookieId - not in integer format!"   
       } 
     }

     

     

    By the way, it looks like the floor() math function is not included in our implementation. I'll verify this and post a list of available builtin functions. Your example would likely cause a runtime violation in the iRule producing an error similar to the following:

     

     

    syntax error in expression "set TempCookieId2 [expr floor $TempCookieId]": variable references require proceeding $...".

     

     

    If you replace your code with floor($TempCookieId) you would get a configuration error stating something like the following:

     

     

    unknown math function "floor" while compiling "expr floor($TempCookieId)...

     

     

    -Joe