TCP::collect

Description

Causes TCP to start collecting the specified amount of content data. After collecting the data in a clientside event, the CLIENT_DATA event will be triggered. When collecting the data in a serverside event, the SERVER_DATA event will be triggered.
Note: If multiple iRules attached to the same virtual execute this command, the last collect wins, meaning the earlier one will be ignored.

It is important to note that, when an explicit length is not specified, the semantics of TCP::collect and TCP::release are different than those of the HTTP::collect and HTTP::release commands. With TCP::collect, the event for processing the data (CLIENT_DATA or SERVER_DATA ) will fire without TCP::release being called, whereas with HTTP::collect, the event (HTTP_REQUEST_DATA or HTTP_RESPONSE_DATA) will not fire without HTTP::release being called.

Syntax

TCP::collect [<collect_bytes> [<skip_bytes>]]

Note: As of 12.0.0, the collect_bytes argument must be a positive integer and the skip_bytes argument must be a non-negative integer.

TCP::collect

  • Collect TCP payload data. The CLIENT_DATA or SERVER_DATA event will be triggered for every received packet. To stop collecting and forward collected or modified payload data, use TCP::release.

TCP::collect <collect_bytes>

  • Collect the specified amount of TCP payload data. The <collect_bytes> parameter specifies the minimum number of bytes to collect. The CLIENT_DATA or SERVER_DATA event will be triggered when the data collection is complete.

TCP::collect <collect_bytes> <skip_bytes>

  • Collect the specified amount of TCP payload data, after skipping the specified amount. The <collect_bytes> parameter specifies the minimum number of bytes to collect, and the <skip_bytes> parameter specifies the number of bytes to skip. The CLIENT_DATA event will be triggered when the data collection is complete, and also when the specified number of bytes have been skipped. In the latter case, there may not be any bytes yet collected ( TCP::payload is empty).
  • Note that the use of the <skip_bytes> parameter changes the timing of serverside connection initiation: Ordinarily, TCP::collect causes the server-side connection to be delayed until the requested data is received. If the <skip_bytes> parameter is specified, even if the value is 0, the serverside connection is not delayed by the TCP profile (other profiles, such as the HTTP profile, may also delay the serverside connection, however). This may be useful in trying to use the same virtual server for both client-initiated protocols (like HTTP) and server-initiated protocols (like SSH). If a load balancing decision needs to be made on client data after <skip_bytes>, it may be necessary to use the LB::detach command to sever the serverside connection before making a new selection.
  • Since the use of the <skip_bytes> requires a serverside connection to be established, there must be a valid load balancing target available. Attempting to use this parameter without a server available to complete the backend handshake (no default pool specified, all servers in pool down, etc.) will result in a RST on the clientside connection.

Note: The parameter has not yet been extensively tested. There are also some important known issues associated with it, such as CR95439 (some commands do not work if the parameter is used; fixed in v9.4.5) and CR101100 (if a packet splits contains enough data to meet but not enough to meet , CLIENT_DATA may not fire; not yet fixed).

Examples

Note: The TCL interpreter has an limit on the maximum size a variable can grow to, which documented at https://support.f5.com/csp/article/K13387. If you use TCP::collect to gather a large amount of data, and then assign that payload to variable, the tmm process will terminate with a memory allocation error. Care should be taken to ensure that TCP::release is call sufficiently often that the buffer does not exceed this limit.
when CLIENT_ACCEPTED {
  TCP::collect 15
}
when CLIENT_DATA {
  if { [TCP::payload 15] contains "XYZ" } {
     pool xyz_servers
  } else {
     pool web_servers
 }
 TCP::release
}

when CLIENT_ACCEPTED {
   log local0.debug "CLIENT_ACCEPTED"
   TCP::collect
}
when CLIENT_DATA {
   set tcplen [TCP::payload length]
   log local0.debug "CLIENT_DATA ($tcplen)"

   #Assume that you need at least 20 bytes of data for some purpose
   if { $tcplen >= 20 } {
     log local0.debug "Collected at least 20 bytes. releasing"
     #Release collected data
     TCP::release
     # Collect new data - CLIENT_DATA will be called again
     TCP::collect
  }
}