Forum Discussion

Omer_ILK_69119's avatar
Omer_ILK_69119
Icon for Nimbostratus rankNimbostratus
May 16, 2013

while loop optimization

Hi All,

 

I'm developing a cgnat irule based on port block allocation algorithm. I have public ip pool like;

 

public1:port1-port2

 

public1:port2-port3

 

public2:port1-port2

 

public2:port2-port3

 

....

 

....

 

 

I'm scanning public ip pool with "while loop" to find an unused publicIP:port part

 

My code has three while loop like

 

set i 1

 

set cnt 1

 

while { $i <= [array size static::Pools] and $cnt } {

 

set j 1

 

while { $j <= [lindex $static::Pools($i) 1] and $cnt } {

 

set k 1

 

while { $k <= $static::NatPortBlock } {

 

incr k

 

}

 

incr j

 

}

 

incr i

 

}

 

 

Three while loop will eat system resources. Do you have any recommendation to find an unused publicip:port part? irule don't have array pop and push functions it may be useful

 

Regards,

 

Omer

 

1 Reply

  • Ouija_Coder_111's avatar
    Ouija_Coder_111
    Historic F5 Account

    It looks like you have a single two dimensional array called $static::Pools and a second array called $static::NatPortBlock, and you'd like to get the first unused element in each. I'd recommend that you store the last index of each using a table command. It would look something like

    
    when RULE_INIT {
        set static::Pools {{"a" "b" "c" }  {"d" "e"} {"f" "g" "h" "i"}}
    }
    when HTTP_REQUEST {
      log local0. "Array size is [llength $static::Pools]"
      set last_dim_one_index [table lookup "last_dim_one_index"]
       if { [string length $last_dim_one_index] == 0  ||
            $last_dim_one_index == [llength $static::Pools]
        } then {
          set last_dim_one_index 0
          table set "last_dim_one_index" 0 indef  indef
    } else {
          table incr "last_dim_one_index"
    }
       set indexkey "column_of_row_$last_dim_one_index"
       set index_two [table lookup $indexkey]
       if { [string length $index_two] == 0  ||
            $index_two == [llength [lindex $static::Pools $last_dim_one_index]]
        } then {
          set index_two 0
          table set $indexkey 0 indef indef
    } else {
          table incr $indexkey
    }
    set myList [lindex $static::Pools $last_dim_one_index]
    set myReturnString "Answer is [lindex $myList $index_two] for $last_dim_one_index and $index_two $indexkey"
    HTTP::respond 200 content $myReturnString
    }
     

    I'm not sure what the relationship between the index of $k and $i or $j is in your example, but I think that in general you can see how to use the table command to simulate your stack. If you'd like to do a "pop", you can just use

     table incr $key -1