In this article, we're going to cover loop control structures and how to gain efficiency therein. One of the things that makes iRules so powerful is the fact that it is effectively a full scripting language at your fingertips with which you can inspect and modify traffic in real time. As with any scripting language, TCL (which iRules is based on) makes use of different loop control structures to perform different tasks. These are usually used in more advanced iRules, but we'll take a look at a couple of simple examples for ease of reading.

In the below examples we're going to be looking at a relatively simple situation. In both we're going to be taking a list of strings, domain names in this case, and cycling through that list one at a time, performing some given tasks on each item in the list.

For & While Loops

In the first examples, we use the for and while loop. These loops are two of the most common loop structures around, and are used in many, many languages. While these examples certainly function, you'll notice there are many steps required to get to the point of actually performing the actions based on the data in question. These are the preferred loops in many languages as they are relatively robust and functional, and the difference in overhead is less important. But this is a bit expensive for iRules, unless there is an actual need. It ultimately doesn't matter if you use a for or while in this scenario, but for loops are far more common in the examples you'll find on DevCentral.

when HTTP_REQUEST {
  set domains {bob.com ted.com domain.com}
  set countDomains [llength $domains]

  #for loop
  for {set i 0} { $i < $countDomains } {incr i} {
    set domain [lindex $domains $i]
    # This is slower
  }

  #while loop
  set i 0
  while { $i < $countDomains } {
    set domain [lindex $domains $i]
    incr i
  }
}

If you do need the additional flexibility with these loops, know that you have continue and break at your disposal as well. The former will stop processing of the current loop, but move on to the next test condition, whereas the latter will exit the loop immediately and move on to the next line of code. It's also important to remember that these loops are blocking, so given the single-threaded nature of TMM, you really don't want to iterate through too many test cases before moving on. Unless of course you are trying to slow BIG-IP down for testing purposes, then, loop away!

Foreach Loops

This next example is logically similar. It accomplishes the same task in this case, and does so with less overhead. See how we have less variables to set, and less functions to perform for each loop iteration? While foreach is sometimes thought of as slightly less powerful or flexible than a for loop, it is markedly more efficient. As such, in cases where it will accomplish the task at hand, it is by far the preferred structure.

when HTTP_REQUEST {
  set domains {bob.com ted.com domain.com}
  foreach domain $domains {
  # This is faster, and more elegant
  }
}

Looping as a Sleep Timer?

Many moons ago someone asked in the forums (yes, we used to have forums) if there was a way to make iRules sleep for a period of time. I was relatively new to iRules but eager to help, so I weighed in that using a for loop with a massive counter would be the way to go. Colin quickly responded that that might not be the best idea, given the blocking nature of doing such a thing and the single threaded nature of TMM I mentioned above. At the time, there wasn't a great way, but you can accomplish this now with the after command, which is non-blocking.