Forum Discussion

wenhu_Tang_7610's avatar
wenhu_Tang_7610
Icon for Nimbostratus rankNimbostratus
Jul 26, 2005

iRules for TCP break up

Hi,

 

 

I want to write an iRules to route a TCP packet according to the payload of the packet, but I fail, could you tell whether it is possible and how to achive?

 

 

my iRules:

 

when CLIENT_ACCEPTED {

 

log "TCP client accepted..."

 

TCP::collect

 

}

 

 

when CLIENT_DATA {

 

log "TCP client data received..."

 

set seq [findstr [TCP::payload] "rtsp:" 0 "\r"]

 

log "seq=$seq"

 

TCP::collect

 

}

 

 

I have done a test, I use a TCP clent to send TCP packet including "rtsp:" in it's content, it seems that the CLIENT_DATA event can only be triggered when the first TCP packet is received after creation of TCP connection.
  • thanks, it works after I add TCP::release.

     

    when CLIENT_ACCEPTED {

     

    log "TCP client accepted..."

     

    TCP::collect

     

    }

     

     

    when CLIENT_DATA {

     

    log "TCP client data received..."

     

    set seq [findstr [TCP::payload] "rtsp:" 0 "\r"]

     

    log "seq=$seq"

     

    TCP::release

     

    TCP::collect

     

    }

     

     

    I have one more question. can I use node command before TCP::release, I want to route the TCP packet to one of the pool member according to the playload.
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Yes, with one caveat - in order to cause the proxy to re-load balance you will first need to call LB::detach.
  • James_Yang_9987's avatar
    James_Yang_9987
    Historic F5 Account
    What LB::detach means and where can I found detailed document about this type of commands?
  • david_wang_2073's avatar
    david_wang_2073
    Historic F5 Account
    I tested following irule, it should work. Here if the payload contain 4, the request will be directed to the 192.168.2.200:3434, otherwise will be directed to the default pool.

    
    when CLIENT_ACCEPTED {
      set index0 1
      TCP::collect
      log local0. "client_accepted"
    }
    when CLIENT_DATA {
      log local0. "client_data to be realesae [TCP::payload]"
      if { [TCP::payload] contains "4" } {
        log local0. "contain 4"
        use node "192.168.2.200" "3434"
      }
      TCP::release
      TCP::collect
      log local0. "client data collect after release [TCP::payload]  --length [TCP::payload length]"
    }
    when SERVER_CONNECTED {
      TCP::collect
      log local0. "server connected"
    }
    when SERVER_DATA {
      if { $index0 == 10 } { 
        log local0. " idnex0 = 10 "
      }
      log local0. "release server data [TCP::payload]  --length [TCP::payload length]"
     
      TCP::release
     
      TCP::collect
      log local0. "collect after release server data [TCP::payload]  --length [TCP::payload length]"
      TCP::notify response
      log local0. "notity response"
    }
    when USER_RESPONSE {
      log local0. "detach"
      LB::detach
    }

    From the output of tcpdump, it can be found that each LB::detach will lead the connection to the node was terminated:

    [root@www:Active] config tcpdump -i internal -n port 3434

    tcpdump: listening on internal

    03:58:50.212175 192.168.0.105.rfe > 192.168.2.11.3434: S 257489860:257489860(0) win 4380 (DF)

    03:58:50.212313 192.168.2.11.3434 > 192.168.0.105.rfe: S 2250864482:2250864482(0) ack 257489861 win 17520 (DF)

    03:58:50.212321 192.168.0.105.rfe > 192.168.2.11.3434: . ack 1 win 4380 (DF)

    03:58:50.212334 192.168.0.105.rfe > 192.168.2.11.3434: P 1:10(9) ack 1 win 4380 (DF)

    03:58:50.215249 192.168.2.11.3434 > 192.168.0.105.rfe: P 1:16(15) ack 10 win 17511 (DF)

    03:58:50.215354 192.168.0.105.rfe > 192.168.2.11.3434: F 10:10(0) ack 16 win 4395 (DF)

    03:58:50.215465 192.168.2.11.3434 > 192.168.0.105.rfe: . ack 11 win 17511 (DF)

    03:58:50.216364 192.168.2.11.3434 > 192.168.0.105.rfe: F 16:16(0) ack 11 win 17511 (DF)

    03:58:50.216378 192.168.0.105.rfe > 192.168.2.11.3434: . ack 17 win 4395 (DF)

    03:58:51.225556 192.168.0.105.rfe > 192.168.2.10.3434: S 3886683331:3886683331(0) win 4380 (DF)

    03:58:51.225690 192.168.2.10.3434 > 192.168.0.105.rfe: S 1671924508:1671924508(0) ack 3886683332 win 17520 (DF)

    03:58:51.225698 192.168.0.105.rfe > 192.168.2.10.3434: . ack 1 win 4380 (DF)

    03:58:51.225711 192.168.0.105.rfe > 192.168.2.10.3434: P 1:10(9) ack 1 win 4380 (DF)

    03:58:51.227084 192.168.2.10.3434 > 192.168.0.105.rfe: P 1:16(15) ack 10 win 17511 (DF)

    03:58:51.227154 192.168.0.105.rfe > 192.168.2.10.3434: F 10:10(0) ack 16 win 4395 (DF)

    03:58:51.227252 192.168.2.10.3434 > 192.168.0.105.rfe: . ack 11 win 17511 (DF)

    03:58:51.227871 192.168.2.10.3434 > 192.168.0.105.rfe: F 16:16(0) ack 11 win 17511 (DF)

    03:58:51.227876 192.168.0.105.rfe > 192.168.2.10.3434: . ack 17 win 4395 (DF)

    03:58:52.233052 192.168.0.105.rfe > 192.168.2.11.3434: S 259607868:259607868(0) win 4380 (DF)

    03:58:52.233190 192.168.2.11.3434 > 192.168.0.105.rfe: S 2251487837:2251487837(0) ack 259607869 win 17520 (DF)

    03:58:52.233199 192.168.0.105.rfe > 192.168.2.11.3434: . ack 1 win 4380 (DF)

    03:58:52.233211 192.168.0.105.rfe > 192.168.2.11.3434: P 1:10(9) ack 1 win 4380 (DF)

    03:58:52.234692 192.168.2.11.3434 > 192.168.0.105.rfe: P 1:16(15) ack 10 win 17511 (DF)

    03:58:52.234809 192.168.0.105.rfe > 192.168.2.11.3434: F 10:10(0) ack 16 win 4395 (DF)

    03:58:52.234919 192.168.2.11.3434 > 192.168.0.105.rfe: . ack 11 win 17511 (DF)

    03:58:52.235535 192.168.2.11.3434 > 192.168.0.105.rfe: F 16:16(0) ack 11 win 17511 (DF)

    03:58:52.235541 192.168.0.105.rfe > 192.168.2.11.3434: . ack 17 win 4395 (DF)

    03:58:53.241064 192.168.0.105.rfe > 192.168.2.200.3434: S 270953496:270953496(0) win 4380 (DF)

    03:58:53.241202 192.168.2.200.3434 > 192.168.0.105.rfe: S 1711048981:1711048981(0) ack 270953497 win 17520 (DF)

    03:58:53.241211 192.168.0.105.rfe > 192.168.2.200.3434: . ack 1 win 4380 (DF)

    03:58:53.241224 192.168.0.105.rfe > 192.168.2.200.3434: P 1:10(9) ack 1 win 4380 (DF)

    03:58:53.243293 192.168.2.200.3434 > 192.168.0.105.rfe: P 1:16(15) ack 10 win 17511 (DF)

    03:58:53.243422 192.168.0.105.rfe > 192.168.2.200.3434: F 10:10(0) ack 16 win 4395 (DF)

    03:58:53.243531 192.168.2.200.3434 > 192.168.0.105.rfe: . ack 11 win 17511 (DF)

    03:58:53.244141 192.168.2.200.3434 > 192.168.0.105.rfe: F 16:16(0) ack 11 win 17511 (DF)

    03:58:53.244149 192.168.0.105.rfe > 192.168.2.200.3434: . ack 17 win 4395 (DF)

    03:58:54.275059 192.168.0.105.rfe > 192.168.2.10.3434: S 3889879731:3889879731(0) win 4380 (DF)

    03:58:54.275191 192.168.2.10.3434 > 192.168.0.105.rfe: S 1672800708:1672800708(0) ack 3889879732 win 17520 (DF)

    03:58:54.275199 192.168.0.105.rfe > 192.168.2.10.3434: . ack 1 win 4380 (DF)

    03:58:54.275212 192.168.0.105.rfe > 192.168.2.10.3434: P 1:10(9) ack 1 win 4380 (DF)

    03:58:54.277161 192.168.2.10.3434 > 192.168.0.105.rfe: P 1:16(15) ack 10 win 17511 (DF)

    03:58:54.277261 192.168.0.105.rfe > 192.168.2.10.3434: F 10:10(0) ack 16 win 4395 (DF)

    03:58:54.277371 192.168.2.10.3434 > 192.168.0.105.rfe: . ack 11 win 17511 (DF)

    03:58:54.278398 192.168.2.10.3434 > 192.168.0.105.rfe: F 16:16(0) ack 11 win 17511 (DF)

    03:58:54.278413 192.168.0.105.rfe > 192.168.2.10.3434: . ack 17 win 4395 (DF)

    But I was told, by setting the virtual server with oneconnect profile, the connection to the node can be retained. I have not get time to try it.
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    What LB::detach means and where can I found detailed document about this type of commands?

     

    LB::detach causes the server-side of the connection to be detached from the client (and closed unless oneconnect is used) and on the next data that the proxy receives, it will re-load-balance to a new pool member.

     

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    But I was told, by setting the virtual server with oneconnect profile, the connection to the node can be retained. I have not get time to try it.

     

    Yes, that's correct. Using oneconnect will keep the server-side connection to a pool member open. I don't think it will work with the "node" though. So, you may want to create a separate pool with the node as a member and use that instead.

     

     

    There are some subtle but important differences between the "node a.b.c.d p" command and the "pool xyz member a.b.c.d p" command.

     

  • david_wang_2073's avatar
    david_wang_2073
    Historic F5 Account
    I used following rule to break a tcp connection, it seems work for synchronization model, which means that the traffic should following the sequence of "request->response->request->response". For each connection, the total transcation time can be been reduced by this way.

    
    when CLIENT_ACCEPTED {
      set command_length 0
      set oper_code 0
      set status 0
      TCP::collect
     }
    when CLIENT_DATA {
    if {([TCP::payload length] >= 38)} 
    {
     binary scan [TCP::payload 16] Ia8a4 command_length oper_code status
     log local. "client data: length $command_length, oper_code $oper_code, status $status" 
     TCP::release command_length
    } else {
     log local0. "request lenght less than 38"
    }
     
    }
     when SERVER_CONNECTED {
      TCP::collect
     }
     
     when SERVER_DATA 
     {
    if {([TCP::payload length] >= 38)} 
    {
     scan [TCP::payload 4] %d command_length 
     binary scan [TCP::payload 16] @4a8a4 oper_code status
     log local. "server [IP::remote_addr] data: length $command_length, oper_code $oper_code, status $status" 
     TCP::release command_length
     if { $oper_code contains "08020101" } {
     
    binding 
      log local0. "after first binding"
     } else {
      TCP::notify resonse
     }
    } else {
     log local0. "request lenght less than 38"
    }
    }
     
     when USER_RESPONSE {
      log local0. "server detach"
      LB::detach
     }
    }

    It was expected bigip can support asynchronous model, which means that the client can send a batch of request, bigip load balance them to servers before all the responses of server was complected, so the servers can handle the requests from the same client parallen.

    In order to do this, I changed the rule to below,

    
    when CLIENT_ACCEPTED {
      set command_length 0
      set oper_code 0
      set status 0
      TCP::collect
     }
    when CLIENT_DATA {
    if {([TCP::payload length] >= 38)} 
    {
     binary scan [TCP::payload 16] Ia8a4 command_length oper_code status
     log local. "client data: length $command_length, oper_code $oper_code, status $status" 
     TCP::release command_length
    if { $oper_code contains "08010101" } { 
     
    #"08020101"为服务器对binding的第一次请求的代码“
      log local0. "after first binding"
     } else {
      TCP::notify request
     }
    } else {
     log local0. "request lenght less than 38"
    }
     
    }
     when SERVER_CONNECTED {
      TCP::collect
     }
     
     when SERVER_DATA 
     {
    if {([TCP::payload length] >= 38)} 
    {
     binary scan [TCP::payload 16] Ia8a4 command_length oper_code status
     log local. "server [IP::remote_addr] data: length $command_length, oper_code $oper_code, status $status" 
     TCP::release command_length
     } else {
     log local0. "request lenght less than 38"
    }
    }
     
     when USER_REQUEST {
      log local0. "server detach"
      LB::detach
     }
    }

    The testing result is that, bigip can load balance of a batch of requests from client, and in oneconnect model, the server can send the response to bigip even after bigip detached the server. The only problem is that the bigip can not return the data received from detached server to the client.

    I am not sure whether it is due to my wrong irule, or it is the limitation of bigip.

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    You should probably not detach (issue the notify request) until after you have received the response from the server. Your rule currently issues the notify request at the beginning of the next request which potentially causes the detach before a response may have been received from the server. The only course I believe you have is to buffer or delay processing of the next request until you have received a response from the currently connected server. Though we have talked about designing a multiplexor where you could service multiple back-end connections at the same time (either repeating or load-balancing), this is not currently available. One-connect provides an already established connection to save the cost/time of establishing a new connection. It doesn't provide a means of concurrently sending data to multiple servers and then reaping the responses from all the servers it sent requests to. Sorry, but you'll have to stick with your first rule implementation.