I'm creating pseudo TCP packet from scratch (based on some existing data) that can be later analysed using Wireshark.
How should I fill out sequence/acknowledgement number so that in Wireshark we can see a clean flow? Currently, I'm seeing TCP retransmission/out of order/previous segment not captured etc.
What I've tried: increment sequence number with the current TCP packet's length, but it didn't work.
(It doesn't necessarily need to makes sense, I should just get rid of the warnings)
Related
If TCP runs out of its sequence number, what will happen?
If it again turns to 0 as the sequence number of the next byte, won't that be considered "duplicate" by the receiver?
If yes, then it has to ignore that byte.
If not, why?
I think, i found the answer.
The answer of this query, lies on one of the TCP option field known as "timestamp". It's in every TCP segment (including data and ACK segments).
Therefore to identify a unique tcp segment, we look for a combination of "timestamp" and "sequence number".
The basic idea is that a segment can be discarded as an old duplicate if it is
received with a timestamp less than some timestamp recently received on this connection.
Example :
Two segments 400:12001 and 700:12001 definitely belongs to two different incarnations.
And this mechanism is known as "PAWS" or protection against wrapped sequence numbers.
Reference: https://www.rfc-editor.org/rfc/rfc1323#page-17
I was doing some experiments.
And I used OnOffApplication to generate the traffic.
However things didn't seem right.
And i use
MaxBytes to send the amount of traffic that I want.
And the traffic is heavy.
So there will be some packets being dropped.
And it seems OnOffApplication doesn't care about the dropped packets. ( I'm not sure. It's my guess)
It only send the packets until it reaches MaxBytes , and doesn't care about whether the packet is received or not.
Is my guess right?
And, if my guess is right, then is there any alternative choice that I can use.
To generate traffic that each flow has a certain size, and have to re-transmit until all packets in the same flow is received.
My code is in below
OnOffHelper source ("ns3::TcpSocketFactory", Address (InetSocketAddress(r_ipaddr, port)));
source.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
source.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
source.SetAttribute ("DataRate", DataRateValue (DataRate(linkBw)));
source.SetAttribute("PacketSize",UintegerValue (packetSize));
source.SetAttribute ("MaxBytes", UintegerValue (tempsize*1000));
From the application point of view, OnOff is only a packet generator. It sends packets with specific characteristics (rate, max number etc). It does not track them. That's by design.
If you use TCP though, then the socket will track and make sure that any lost segments are re-transmitted.
The application will generate the MaxBytes in terms of load, but the actual packets transmitted on the wire (or the air) may differ due to the fact that TCP (by design) does not respect the message boundaries, as it is a bytestream oriented protocol. So it may boundle data packets together, or packet segments, with re-trasnmitted segmets etc.
The TCPv4 specification (RFC 793) classifies a received segment as unacceptable if it has zero length, a sequence number equal to RCV.NXT+RCV.WND while the receive window is not zero (second row in the table).
This essentially means that the segment will be discarded, other than possibly sending an ACK. No ACK processing or send window update will be done.
What is the justification of this?
Consider this scenario:
Host A sends all possible data segments to host B, just exhausting the receive window of B.
Host A shortly also sends an empty segment, e.g. a window update or acknowledgement of received data. This segment has sequence number equal to the right edge of the receive window of host B (RCV.NXT+RCV.WND), since it was set to the latest SND.NXT of host A.
The mentioned data packets are lost in the network or delayed, and host B receives the empty segment first.
Host B will classify the empty segment as not acceptable, and drop it, ignoring any acknowledgement or window update.
Is there some part that I am not understanding correctly? Is this scenario really possible?
note: I ask here instead of on networkengineering.stackexchange.com since I encountered the issue while implementing a TCP/IP stack and these protocol details seem closer to programming than what is commonly understood as network engineering.
In TCP, Initial Sequence Numbers are set on a clock and are incremented every 4 microseconds.
Suppose (IP#1, port#1) and (IP#2, port#2) set up a TCP connection and with the respective Initial Sequence Number-s as
ISN1=100, ISN2=500.
A millisecond after, (IP#1, port#1) and (IP#2, port#2) are setting up another TCP connection
with the applying ISN numbers. In this case, the sequence numbers of the first and the
second connections are likely to coincide.
How does TCP handle this? It can reset and thus re-synchronize a connection under
certain circumstances along the way when the sequence numbers are odd (not synchronizing), but this may not cover every case.
How are the sequence numbers handled in such a case when these numbers of
2 different TCP connections may interfere with those of one another?
TIA.
Each TCP connection is identified by a tuple of [ local address, remote address, local port, remote port]. The sequence number is part of the state associated with that key therefore it doesn't matter at all if sequence numbers overlap.
Your particular example is impossible. You cannot setup two different TCP connections with identical local and remote addresses and ports.
I was trying to read some messages from a tcp connection with a redis client (a terminal just running redis-cli). However, the Read command for the net package requires me to give in a slice as an argument. Whenever I give a slice with no length, the connection crashes and the go program halts. I am not sure what length my byte messages need going to be before hand. So unless I specify some slice that is ridiculously large, this connection will always close, though this seems wasteful. I was wondering, is it possible to keep a connection without having to know the length of the message before hand? I would love a solution to my specific problem, but I feel that this question is more general. Why do I need to know the length before hand? Can't the library just give me a slice of the correct size?
Or what other solution do people suggest?
Not knowing the message size is precisely the reason you must specify the Read size (this goes for any networking library, not just Go). TCP is a stream protocol. As far as the TCP protocol is concerned, the message continues until the connection is closed.
If you know you're going to read until EOF, use ioutil.ReadAll
Calling Read isn't guaranteed to get you everything you're expecting. It may return less, it may return more, depending on how much data you've received. Libraries that do IO typically read and write though a "buffer"; you would have your "read buffer", which is a pre-allocated slice of bytes (up to 32k is common), and you re-use that slice each time you want to read from the network. This is why IO functions return number of bytes, so you know how much of the buffer was filled by the last operation. If the buffer was filled, or you're still expecting more data, you just call Read again.
A bit late but...
One of the questions was how to determine the message size. The answer given by JimB was that TCP is a streaming protocol, so there is no real end.
I believe this answer is incorrect. TCP divides up a bitstream into sequential packets. Each packet has an IP header and a TCP header See Wikipedia and here. The IP header of each packet contains a field for the length of that packet. You would have to do some math to subtract out the TCP header length to arrive at the actual data length.
In addition, the maximum length of a message can be specified in the TCP header.
Thus you can provide a buffer of sufficient length for your read operation. However, you have to read the packet header information first. You probably should not accept a TCP connection if the max message size is longer than you are willing to accept.
Normally the sender would terminate the connection with a fin packet (see 1) not an EOF character.
EOF in the read operation will most likely indicate that a package was not fully transmitted within the allotted time.