F5 is upgrading its customer support chat feature on My.F5.com. Chat support will be unavailable from 6am-10am PST on 1/20/26. Refer to K000159584 for details.

Forum Discussion

U_franco_117956's avatar
U_franco_117956
Icon for Nimbostratus rankNimbostratus
Oct 02, 2013

TCL error - no such pool

Hi.

 

We are trying to use a modified irule documented in devcentral to encrypt and maintain cookie persistence across Pools and Services https://devcentral.f5.com/wiki/iRules.Cookie_Encryption_across_pools_and_services.ashx. (It´s needed to maintain persistence between HTTP and HTTPS vservers with the same IP addresses (and with the same nodes). We have applied the following code as vserver resource in HTTP/HTTPS (not as irule linked to universal persistence profile, and this configured as persistence profile in HTTP/HTTPS vservers):

 

when HTTP_REQUEST { If the cookie exists, connect to the IP spACCMfied in the cookie if { [HTTP::cookie exists "ACCM"] } { set need_cookie 0 set decrypted [HTTP::cookie decrypt "ACCM" "skyisblue"] if { ($decrypted ne "") } { log local0. "REQUEST - El host [HTTP::host] se dirige al pool member $decrypted" set persist_node [HTTP::cookie "ACCM"] log local0. "El pool del miembro es: [LB::server pool]" foreach member [active_members -list [LB::server pool]] { set node [lindex $member 0] if { $node eq $persist_node } { node $persist_node [lindex $member 1] } } } } else { set need_cookie 1 } } when LB_FAILED { set need_cookie 1 LB::reselect } when HTTP_RESPONSE { if { $need_cookie } { HTTP::cookie insert name "ACCM" value [IP::remote_addr] path / HTTP::cookie encrypt "ACCM" "skyisblue" HTTP::cookie expires "ACCM" 86400 } }

 

All seems to work fine. However we are receiving this kind of errors in ltm log when I try to refresh several times the same web page:

 

Oct 2 13:42:12 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: /CISCOPRE/ACCMOINSA_HTTP Oct 2 13:42:12 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: Oct 2 13:42:12 slot1/LTMPRE1 err tmm[10605]: 01220001:3: TCL error: /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM - no such pool: (line 9) invoked from within "active_members -list [LB::server pool]" Oct 2 13:42:12 slot1/LTMPRE1 info tmm1[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: /CISCOPRE/ACCMOINSA_HTTP Oct 2 13:42:17 slot1/LTMPRE1 info tmm1[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: /CISCOPRE/ACCMOINSA_HTTP Oct 2 13:42:17 slot1/LTMPRE1 info tmm1[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: Oct 2 13:42:17 slot1/LTMPRE1 err tmm1[10605]: 01220001:3: TCL error: /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM - no such pool: (line 9) invoked from within "active_members -list [LB::server pool]" Oct 2 13:42:17 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: /CISCOPRE/ACCMOINSA_HTTP Oct 2 13:42:17 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: Oct 2 13:42:17 slot1/LTMPRE1 err tmm[10605]: 01220001:3: TCL error: /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM - no such pool: (line 9) invoked from within "active_members -list [LB::server pool]" Oct 2 13:42:17 slot1/LTMPRE1 info tmm1[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: /CISCOPRE/ACCMOINSA_HTTP Oct 2 13:42:18 slot1/LTMPRE1 info tmm1[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: Oct 2 13:42:18 slot1/LTMPRE1 err tmm1[10605]: 01220001:3: TCL error: /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM - no such pool: (line 9) invoked from within "active_members -list [LB::server pool]" Oct 2 13:42:18 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : El pool del miembro es: /CISCOPRE/ACCMOINSA_HTTP

 

Please, anybody could help us to troubleshoot why we are receiving this kind of tcl errors?

 

B.R.

 

5 Replies

  • Ops!! I hope now irule will be more readable

    when HTTP_REQUEST {
         If the cookie exists, connect to the IP spACCMfied in the cookie
        if { [HTTP::cookie exists "ACCM"] } {
             set need_cookie 0
             set decrypted [HTTP::cookie decrypt "ACCM" "skyisblue"]
             if { ($decrypted ne "") } {
                   log local0. "REQUEST - El host [HTTP::host] se dirige al pool member $decrypted"
                  set persist_node [HTTP::cookie "ACCM"]
                  log local0. "El pool del miembro es: [LB::server pool]"
                    foreach member [active_members -list [LB::server pool]] {
                       set node [lindex $member 0]
                            if { $node eq $persist_node } {
                                 node $persist_node [lindex $member 1]
                            }
                   }
            }
        } else {
             set need_cookie 1
             }
    }
    when LB_FAILED {
        set need_cookie 1
        LB::reselect
    }
    when HTTP_RESPONSE {
       if { $need_cookie } {
           HTTP::cookie insert name "ACCM" value [IP::remote_addr] path /
           HTTP::cookie encrypt "ACCM" "skyisblue"
           HTTP::cookie expires "ACCM" 86400
       }
    }
    
  • It would appear that [LB::server pool] loses context somewhere inside the TCP session. It would appear that you're looping through each active pool member (on each request) to see if the persisted node (from the cookie) is in the active list. Here is a slightly different, and hopefully slighter more optimized approach:

    when RULE_INIT {
        set static::COOKIEKEY "skyisblue"
    }
    when CLIENT_ACCEPTED {
        set default_pool [LB::server pool]
    }
    when HTTP_REQUEST {
         If the cookie exists, connect to the IP spACCMfied in the cookie
        if { [HTTP::cookie exists "ACCM"] } {
            set decrypted [HTTP::cookie decrypt "ACCM" $static::COOKIEKEY]
            if { $decrypted ne "" } {
                 Make sure node in cookie value is still viable
                if { [LB::status pool $default_pool member [lindex [split $decrypted "%"] 0] [lindex [split $decrypted "%"] 1]] eq "up" } {
                     Send to persisted pool member
                    pool $default_pool member [lindex [split $decrypted "%"] 0] [lindex [split $decrypted "%"] 1]
                } else {
                     Pool member is down - automatically select new pool members and send new cookie
                    set need_cookie 1
                }
            }
        } else {
            set need_cookie 1
        }
    }
    when HTTP_RESPONSE {
        if { [info exists need_cookie] } {
            unset need_cookie
            HTTP::cookie insert name "ACCM" value "[IP::remote_addr]%[TCP::remote_port]" path /
            HTTP::cookie encrypt "ACCM" $static::COOKIEKEY
            HTTP::cookie expires "ACCM" 86400
        }
    }
    

    This version puts both the IP and port into the encrypted cookie, and then simply checks to make sure this node is still "up" in the pool before sending traffic to it. If the pool member is down, auto-selection will happen and the client will get a new persistence cookie.

    You could also potentially just enable cookie encryption in the HTTP profile. It won't change the cookie name (BIGipServer[pool name]), but the value will be encrypted with your passphrase.

  • Ahh, I didn't get that at first. I would just go back to hard coding the port then.

     

  • Thanks very much for your help Kevin.

     

    Meanwhile, I think it´s a good idea the way you verify pool member status and how it is selected. It´s not needed to look for the pool member in a list, because it´s hardcoded into cookie value. So I have tried to use that portion of your code into iRule I was testing:

     

    HTTP_REQUEST {
        if { [HTTP::cookie exists "ACCM"] } {
                      set need_cookie 0
            set decrypted [HTTP::cookie decrypt "ACCM" "skyisblue"]
            if { ($decrypted ne "") } {
                          set persist_node [HTTP::cookie "ACCM"]
                            log local0. "Pool: [LB::server pool], server: $decrypted ,port: [LB::server port]"
                            if { [LB::status pool [LB::server pool] member $decrypted [LB::server port]] eq "up" } {
                    pool [LB::server pool] member $decrypted [LB::server port]
                } else {
                        set need_cookie 1
                }
            }
        } else {
             set need_cookie 1
             }
    }
    when LB_FAILED {
             set need_cookie 1
        LB::reselect
    }
    when HTTP_RESPONSE {
       if { $need_cookie } {
           HTTP::cookie insert name "ACCM" value [IP::remote_addr] path /
           HTTP::cookie encrypt "ACCM" "skyisblue"
           HTTP::cookie expires "ACCM" 86400
       }
    }

    As you can see, I have configured a log local0. in order to obtain pool name, selected server and server port. Taking a view to ltm log, I can see log messages in which port always is 0. I don´t know why [LB::server port] returns 0 value:

     

    Oct  4 10:34:22 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : Pool: /CISCOPRE/ACCMOINSA_HTTP, server: 192.168.202.223%10 ,port: 0
    Oct  4 10:34:22 slot1/LTMPRE1 info tmm[10605]: Rule /Common/iRULE_PERSISTENCE_HTTP_HTTPS_ACCM : Pool: /CISCOPRE/ACCMOINSA_HTTP, server: 192.168.202.223%10 ,port: 0

    Am I doing something wrong??

     

    B.R.

     

  • You're going to run into the same problem you had previously using LB::server pool and LB::server port in the HTTP_REQUEST event. The most important thing to consider is that the HTTP_REQUEST event is triggered BEFORE the LB_SELECTED event, so while the values may be there sometimes (as you've discovered), it won't always be there. If you truly need to use LB::server commands in an HTTP_REQUEST event, try moving the whole thing to HTTP_REQUEST_SEND or HTTP_REQUEST_RELEASE instead.

     

    Also, while you're doing HTTP and HTTPS on the outside, the pool members should all still be port 80, so you could simply hard code the port in the LB::status event.