Forum Discussion
Tiaan_92076
Nimbostratus
Aug 18, 2009How to determine last segment in reaseembled TCP packet
I need to detach the load balancing decision after a transaction is completed on a member in the pool. The transaction occasionally spans multiple TCP segments causing the SERVER_DATA event to be raised more than once for the same transaction. With "LB::detach" in the "SERVER_DATA" event the transaction fails when this happens.
Implementing the "if" statement to check if the payload ends with a certain string and then calling "TCP::notify response" to run "LB::detach" in the "USER_RESPONSE" event solves the problem. Example below from the documentation.
when SERVER_DATA {
log local0.debug "Received SERVER response ... [TCP::payload]"
if { [TCP::payload] ends_with $EOT } {
TCP::notify response
}
TCP::release
TCP::collect
}
when USER_RESPONSE {
LB::detach
log local0.debug "Detaches server connection ... "
if {[TCP::payload length] > 0} {
%TODO%
Process additional client requests here ...
}
}
Can the same be done without checking the payload ? Possibly an event fired when the last segment is received ? I could not find this in the documentation though.
Thanks
18 Replies
- spark_86682Historic F5 AccountWithout being able to parse the protocol, there's no way for the LTM to know which segment is last. If you are able to figure out how many bytes are in the response (e.g., from parsing the protocol headers), then you can just TCP::collect that many bytes, and SERVER_DATA will only fire when it has the entire response.
- Tiaan_92076
Nimbostratus
So Wireshark can reassemble the packet because it understands the protocol, GIOP in this case, and already have all the TCP segments ?
I've looked at the suggestion to parse the protocol headers for the length of the packet. GIOP has a header for message size, but there are multiple GIOP messages per TCP segment. Determining the number of GIOP messages and summing the message size headers would probably be a more expensive operation than just checking the end of the payload for a specific string ? - spark_86682Historic F5 AccountLooking briefly at the protocol spec, yes, that probably would be more expensive than checking to see if you've got the end-of-transaction marker. If it works for you, then you probably already have the best solution.
- Tiaan_92076
Nimbostratus
I've got the following problem with my iRule when a client uses multiple threads using the same source port for all the threads.
Doing a TCPDump I can see the transactions coming in on the outside interface, on the inside interface it goes the the nodes and I can see the response returned from the nodes. But I don't see the response leaving the outside interface. The result is that the client don't get the response and eventually times out.
iRule:when RULE_INIT { set ::eot "Marker" set ::eot_found 0 } when SERVER_CONNECTED { TCP::collect } when SERVER_DATA { set payload [TCP::payload] log -noname local0. "iRule: Request from [IP::client_addr]:[TCP::client_port] load balanced to [LB::server addr]" if { $payload ends_with $::eot } { set ::eot_found 1 } TCP::release TCP::collect TCP::notify response } when USER_RESPONSE { if { $::eot_found eq 1 } { set ::eot_found 0 LB::detach } }
After adding the "log" to "SERVER_CONNECTED" event I get the following error in the log file. Without this line no errors were logged.
TCL error: - Error: No clientside connection established (line 6) invoked from within "IP::client_addr"
Why would doing a LB detach effect the client side connection ?
Thanks
Tiaan - spark_86682Historic F5 AccountI'm not 100% sure that I understand why you'd get that error just by adding that log statement, but to answer your stated question: LB::detach severs the relationship between the client<->LTM connection and the LTM<->server connection. That's what it's there for; that's what "detaching" is. So once you've detached, well, there is no more clientside connection for this server connection, so that's why you get that error when you ask for the client's address.
- Tiaan_92076
Nimbostratus
That is not how I understood the LB::detach command, the documentation says it only disconnects the server side connection?
Looking at the TCPDump on the client<->LTM side of the connection I don't see the connection being closed. It is as if the traffic just disappears.
The iRule works perfectly, it's only when the client is multi-threaded and using the same source port for all threads when the issue occurs. - spark_86682Historic F5 AccountYes, it disconnects it from the client side connection. It doesn't close either the server or client side connections, it just severs the relationship between them. It disconnects them from each other.
I suspect that there is something more going on than just that the client is multi-threaded. Is it that multiple requests are outstanding on the same TCP connection when it is?
If you're trying to independently load balance multiple requests in the same connection, then you need to add some client-side buffering to your iRule. So make sure to only send one request to the server, then parse it for the end of the response, then do an LB::detach and then TCP::release the next request so that another LB choice is made and another server connection is chosen. - Tiaan_92076
Nimbostratus
Is it that multiple requests are outstanding on the same TCP connection when it is?
Yes, all the client side requests are in the same TCP connection. There is always at least one response returned on to the client. All the requests are responded to by the application nodes but as you pointed out the relationship between the client and server side of the connection is not there anymore, therefore these responses don't reach the client.
How would I implement client-side buffering ?
Thanks - Tiaan_92076
Nimbostratus
I've tested the iRule on a v10 device and noticed not all of my "log" entries were written to the log.
I then tested with the following iRule, and again some of the log entries are missing. All transactions in the application were successful.when SERVER_CONNECTED { TCP::collect } when SERVER_DATA { log -noname local0. "iRule: Received Server Data" TCP::collect TCP::release }
Does v10 limit the number of log entries ? - hoolio
Cirrostratus
The is probably from syslog-ng suppressing duplicate messages:http://devcentral.f5.com/wiki/default.aspx/iRules/log
...syslog-ng will still perform suppression of repeated duplicates.
From the syslog-ng v2.0 manual, there is a suppress option which will summarize all duplicate messages within an interval. By default this is disabled though. And I couldn't find anywhere in the default syslog-ng.conf or 'b syslog list all' output where it is configured. But I have seen this suppression consistently when logging duplicate messages in quick succession.
http://www.balabit.com/dl/guides/syslog-ng-v2.0-guide-admin-en.pdf
Name: suppress()
Type: seconds
Default: 0 (disabled)
Description:
When enabled and syslog-ng would send several messages
with identical content to the destination, syslog-ng sends only
a single message and a line Last message repeated n
times.. The parameter of this option specifies the number of
seconds syslog-ng waits for identical messages.
Aaron
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects