Forum Discussion

Mark_Moseley's avatar
Mark_Moseley
Icon for Nimbostratus rankNimbostratus
Nov 14, 2005

Predefining variables and how iRules work

Hi. This is a two-parter, neither of which I can find answers for but might be using the wrong search terms (in which case, my apologies).

 

 

1) Is it possible to pre-define variables in iRules? Just declaring them outside of a when {} context doesn't seem to work:

 

 

Gives this error:

 

line 1: [command is not valid in the current scope] [set hi hi]

 

 

I've got a hash map I'd like to use that could be upwards of a few hundred entries, so it'd be nice to not have to initialize the variable over and over. Is there another way to do this?

 

 

 

2) Related to 1, I'm curious how iRules are stored in memory. Is the script compiled to some sort of byte-code at first run and then run from byte-code (or something similar), or is run through the BigIP's implementation of a tcl interpreter from scratch each time? The upshot is I'm wondering if there are optimizations that the BigIP already does that would make it not as necessary for me to worry about 1.]

 

 

Thanks!

4 Replies

  • You can build string or address classes, and they can be stored in the bigip.conf file, or externally in the profile_base.conf file. See:

     

     

    bigpipe class help

     

     

    No idea on the 2nd question. My understanding is that the rules are in memory once loaded (in fact, some rule fragments that are deleted require a bigstart restart to completely remove them from memory) and that many of the features in the profiles are compiled, and thus, highly optimized, iRules (as explained by one of the ENE's).

     

     

    Some examples from profile_base.conf

     

     

    This is a pre-defined class identifying common image file extensions

     

    class images {

     

    ".jpg"

     

    ".gif"

     

    ".bmp"

     

    }

     

     

    This is a pre-defined class identifying private network addresses.

     

    class private_net {

     

    network 10.0.0.0 mask 255.0.0.0

     

    network 172.16.0.0 mask 255.240.0.0

     

    network 192.168.0.0 mask 255.255.0.0

     

    }

     

     

     

     

     

     

  • As citizen_elah mentioned, in most cases you can create data groups (string, address, etc). As long as the list is static, then this should work out for you. All code must exist within an event construct.

     

     

    But, for your situation, we have a special event mainly desiged for this purpose.

     

    the RULE_INIT event.

     

     

    when RULE_INIT {
      set ::global_var "some value"
    }

     

     

    This event is raised once at load time of the rule.

     

     

    This leads into question 2. Rules are compiled into byte code at load time. They are not interpreted from source on each processing of the rule.

     

     

    Creating a slew of variables in events is not advised if they are static in nature as that takes memory allocations on each connection which can be very costly. An external data group, or a global variable will only incur a single memory allocation for them. Keep in mind though that all connections will have access to these variables so try to avoid modifications of the global vars to avoid contentions between the different connections.

     

     

    -Joe
  • 1) Excellent, this is perfect. I hadn't looked at data groups for this, since they don't appear to allow for non-scalar datatypes. Am I wrong? I'm using a couple of arrays with names (extracted from the hostname) as keys, which looks to be beyond what you can put into a data group. But being able to put it into the INIT event is perfect. There's no terrible overhead there? The actual data is pretty small, probably no more than a 10K altogether. There's just a bunch of them.

     

     

    2) This is all good info. One question springs to mind though, related to what you said about creating variables. Is it a safe generalization to say that for maximum performance, you should always use the functions like [HTTP::path] instead of assigning that to a variable and using the variable? I'd figured that accessing the variable would always be better (assuming you're looking at it more than once of course), just to save the overhead of calling a function/method/subroutine. In the iRules I'm thinking of, something like HTTP::path would get referenced 2 or 3 times. Would [HTTP::Path] be preferable to a variable in that case?

     

     

    Thanks!
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Many of our commands cache the result to improve performance for repeated calls. The performance of caching the result is similar to using a variable but it doesn't have the overhead of having to allocate a context frame to hold the variable.