Forum Discussion

Peter_Reilly's avatar
Peter_Reilly
Icon for Nimbostratus rankNimbostratus
Feb 08, 2005

how to log dropped sessions

I would like to be able to use an iRule to log whenever a tcp session is dropped due to it reaching the tcp timeout value specified in a profile. Is there a mechanism to do this within iRules?

8 Replies

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    There is currently no command that returns the amount of idle time a connection has experienced. I will look into adding this to the IP::stats command.

    The IP::stats command currently has the following options:

    IP::stats pkts in - returns number of packets received

    IP::stats pkts out - returns number of packets sent

    IP::stats pkts - returns a Tcl list of packets in and packets out

    IP::stats bytes in - returns number of bytes received

    IP::stats bytes out - returns number of bytes sent

    IP::stats bytes - returns a Tcl lost of bytes in and bytes out

    IP::stats age - returns the age of the connection in seconds

    (number of seconds since 3-way handshake completed).

    The CLIENT_CLOSED event can be used to check the above stats when the connection is closed.

    You could therefore attempt to synthesize the idle time like so:

     
     when CLIENT_ACCEPTED { 
        set prev_age 0 
     } 
     when HTTP_REQUEST { 
        set prev_age [IP::stats age] 
     } 
     when HTTP_RESPONSE { 
        set prev_age [IP::stats age] 
     } 
     when CLIENT_CLOSED { 
        if { [expr [IP::stats age] - $prev_age] > [IP::idle_timeout] } { 
           log "Client: [IP::remote_addr]:[TCP::remote_port] timed out" 
        } 
     } 
     

    I have created a CR to add the following additional option to the IP::stat command:

    IP::stats idle - return the number of seconds the connection has been idle.

  • rapmaster_c_127's avatar
    rapmaster_c_127
    Historic F5 Account
    Sure, just set a variable to record the URI in the request:

       
           when CLIENT_ACCEPTED {        
               set prev_age 0 
               set req_uri "none"     
           }     
           when HTTP_REQUEST {   
               set prev_age [IP::stats age]   
               set req_uri [HTTP::uri]   
           }     
           when HTTP_RESPONSE {   
               set prev_age [IP::stats age]   
           }     
           when CLIENT_CLOSED {   
               if { [expr [IP::stats age] - $prev_age] > [IP::idle_timeout] } {   
                   log "Client: [IP::remote_addr]:[TCP::remote_port] requesting $req_uri timed out"        
               }     
           }   
       
  • I get the following:

     

     

    Rule logDropped - can't read "req_uri": no such variable while executing "log...

     

     

  • rapmaster_c_127's avatar
    rapmaster_c_127
    Historic F5 Account
    Did you put the

    set req_uri "none"

    in CLIENT_ACCEPTED? I added that after-the-fact; I'd initially failed to consider the case when someone connected and timed out without making a request.

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Also, I should point out that this method needs a little more work to make it absolutely complete. Basically, a large GET (or PUT) could potentially be confused with a timeout since the prev_age is only updated when the HTTP REQUEST or RESPONSE headers are parsed.

    So, to do this correctly, we really need to trigger off all data going through the connection and to do that, we need to use the CLIENT_DATA and SERVER_DATA events.

     
     when CLIENT_ACCEPTED { 
        set prev_age 0 
        TCP::collect 
        set url "" 
     } 
     when CLIENT_DATA { 
        set prev_age [IP::stats age] 
        TCP::release 
        TCP::collect 
     } 
     when HTTP_REQUEST { 
        set url [HTTP::host][HTTP::uri] 
     } 
     when SERVER_CONNECTED { 
        TCP::collect 
     } 
     when SERVER_DATA { 
        set prev_age [IP::stats age] 
        TCP::release 
        TCP::collect 
     } 
         
     when CLIENT_CLOSED { 
        if { [expr [IP::stats age] - $prev_age] > [IP::idle_timeout] } { 
           log "Client: [IP::remote_addr]:[TCP::remote_port] - $url - timed out" 
        } 
     } 
     
  • Is this really in seconds? I think it is in miliseconds.

     

     

    IP::stats age - returns the age of the connection in seconds

     

    (number of seconds since 3-way handshake completed).

     

     

    If so, the condition should be

     

    [expr [IP::stats age] - $prev_age] > [expr [IP::idle_timeout] * 1000]

     

     

    Please let me know so I can use the iRule...
  • I used the code:

     

    when CLIENT_ACCEPTED {

     

    set prev_age 0

     

    }

     

    when HTTP_REQUEST {

     

    set prev_age [IP::stats age]

     

    }

     

    when HTTP_RESPONSE {

     

    set prev_age [IP::stats age]

     

    }

     

    when CLIENT_CLOSED {

     

    set timeout [expr { [IP::idle_timeout] * 1000 } ]

     

    log "Stats age is [IP::stats age] prev age is $prev_age timeout is $timeout"

     

    idle_timeout is in seconds, stats age is in milliseconds

     

    if { [expr [IP::stats age] - $prev_age > $timeout ] } {

     

    log "Client: [IP::remote_addr]:[TCP::remote_port] timed out"

     

    }

     

    }

     

    and found that the timeout is 300000 milliseconds. However, in some cases, which seem to be related to ramcache, the timeout is 5000 milliseconds.