Commit 47925cee authored by Pramod R Sanaga's avatar Pramod R Sanaga

Modified the Design doc to reflect discussion with Rob & Jon.

Changed the throughput calculation, cleaned up MaxDelay and
all other files in general to be more readable.

Added checks for out of order ACKs, and error conditions to
check for invalid packets.

sendto() calls block on Linux - verified this on
planet lab - made the writes to UDP socket non-blocking.
parent 7f75430b
......@@ -62,6 +62,20 @@ the throughput calculations resilient to the loss of a small number of
( 3 consecutive ACK packets can be dropped without any effect on the
throughput calculation ) ACK packets on the reverse path.
The ACK packets also contain the timestamps at the receiver when the original
packets were received. The timestamp for the packet being ACKed is an
absolute value ( in micro seconds ), and the values for redundant ACKs are
relative to this absolute value.
As of now, the acknowledgement packets are of the same size as the received
data packets. If they are a fixed minimum size, then it could affect the RTT
calculations. If the packets sent from nodeA -> nodeB are say 1500 bytes long
and the ACK packets are about 50 bytes, then the transmission delay on the forward
path is going to be more than the transmission delay on the reverse path.
When one way delay is calculated as half of RTT, this causes the one way delay
estimate to be lower the actual value for the forward path ( if the ACKs are a fixed minimum size).
Minimum Delay:
-------------
......@@ -82,43 +96,14 @@ way delay and the minimum from above, gives the value of approximate maximum que
on the forward path. Whenever there is a new maximum queuing delay value, an event is sent to the
application monitor and the value is used to set the maximum queue size for the dummy net pipe.
Throughput (available bandwidth):
---------------------------------
For each acknowledged packet ( assuming no dropped packets ):
Throughput = ( data size of the packet + header overhead ) / ( total one way delay for the packet )
If every packet sent from nodeA is acknowledged by nodeB and there is no packet loss on
either the forward or the reverse path, the above equation gives the throughput for
each packet sent. Taking into account packet drops on the forward path and some packet
drops on the reverse path, the throughput is calculated as below.
Whenever packets are sent by nodeA, information about the sequence number, timestamp and
the size of data in the packet is stored in a list at nodeA. When an acknowledgement
is received, all the packets being acknowledged ( including any of redundant sequence
numbers in the acknowledgement ) are removed from that list and used for throughput
calculation. The sum of these packet sizes gives the amount of data that was transferred
in this round trip time.
After the redundant acknowledgements are considered, any packets remaining in the list with
sequence numbers less than the latest acknowledged sequence number: were either lost in
the forward path, or their ACK packets were lost on the reverse path. We cannot distinguish
between forward/reverse path loss and consider them as forward path loss in both cases.
These lost packets are also removed from the list at nodeA. The start_time of the round trip
for throughput calculation is taken as the earliest send time of all the lost packets and
all the acknowledged packets. The end_time of the round trip is the time at which the
current acknowledgement was received.
The throughput is then = ( sum of data size of ACKed packets ) / ( 0.5 * (end_time - start_time ) )
Note: UDP packets sent by from nodeA may not always be the maximum sized packets, as is most
often the case with TCP. So, the minimum and maximum delay values need to be calculated ( ideally for
every packet size), keeping the maximum sized UDP packet in mind. The one way delay values are
thus scaled to represent maximum sized packets. ( we divide the one way delay by number of bytes in
the packet + overhead, and then multiply it by 1500 ).
Note:
-----
There is another way in which throughput can be calculated. The receiver(nodeB) can timestamp
packets when they are received and send these timestamps in the ACK packets.
Throughput:
-----------
Throughput = (size of data being ACKed) / ( last_receiver_time_stamp - current_receiver_time_stamp )
......@@ -127,6 +112,9 @@ assumption is that there is a single bottleneck link in the network: and the pac
by the receiver will be spaced ( in time ) depending on the queueing & transmission delays
encountered by the packets at the bottleneck.
We assume that the forward and reverse paths are symmetric, in terms of the path
capacity and delay introduced - although this might not be true in some cases.
However, the spacing between the packets at the receiver need not be the same as that
at the bottleneck.This spacing can become compressed(similar to TCP ACK compression) later on in
the network ( at a fast link for example ),and it is possible for the packets to arrive
......@@ -139,10 +127,8 @@ The reason for this is that we fail to take queuing delay into account for close
packets arriving at the receiver. Since the clocks are not synchronized between the sender and
receiver, it is not possible to accurately calculate the one way delay at the receiver.
Hence, throughput values are being calculated at the sender based on the one way delay for
each packet. However, this means that the throughput value will be effected by the RTT
calculation. We assume that the forward and reverse paths are symmetric, in terms of the path
capacity and delay introduced - although this might not be true in some cases.
This compression of packets can affect the throughput calculated - currently we do not of
any way to avoid this potential problem. ( it does seem to occur infrequently, only on a few paths ).
Problems that might crop up:
......@@ -170,5 +156,14 @@ affected by the packet drop problem.
This is just a hypothesis and needs to be tested on planetlab.
2) Reordering of packets on the forward path & reordering of ACKs on the reverse path
We currently ignore the reordering of packets/ACKs on forward/reverse paths.
If this happens persistently and is perceived as a characteristic of some links,
then it might need to be addressed.
This diff is collapsed.
......@@ -22,7 +22,7 @@
#define REMOTE_SERVER_PORT 1500
#define MAX_MSG 1600
#define SNAPLEN 96
#define SNAPLEN 128
#include "UdpThroughputSensor.h"
#include "UdpMinDelaySensor.h"
......@@ -325,6 +325,18 @@ int main(int argc, char *argv[])
exit(1);
}
// Change the socket descriptor to non-blocking.
flags = fcntl(sd, F_GETFL, 0);
flags = flags | O_NONBLOCK;
int readFlags = flags;
// Set the socket descriptor to be non-blocking.
if( fcntl(sd, F_SETFL, flags) < 0)
{
printf("Error setting non blocking socket flags with fcntl.\n");
exit(1);
}
/* bind any port */
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
......@@ -367,17 +379,6 @@ int main(int argc, char *argv[])
FD_ZERO(&readFdSet);
FD_ZERO(&writeFdSet);
// Change the socket descriptor to non-blocking.
flags = fcntl(sd, F_GETFL, 0);
flags = flags | O_NONBLOCK;
int readFlags = flags;
// Set the socket descriptor to be non-blocking.
if( fcntl(sd, F_SETFL, flags) < 0)
{
printf("Error setting non blocking socket flags with fcntl.\n");
exit(1);
}
// Read the command line arguments.
// Number of packets, Size of the packets to be sent, and their sending rate.
......@@ -402,11 +403,11 @@ int main(int argc, char *argv[])
{
// UDP sends do not block - we don't need to
// check if the socket is ready for writing.
// FD_SET(sd, &writeFdSet);
FD_SET(sd, &writeFdSet);
// select(1024,NULL,&writeFdSet, NULL,&selectTimeout);
select(sd + 1,NULL,&writeFdSet, NULL,&selectTimeout);
// if(FD_ISSET(sd, &writeFdSet) != 0)
if(FD_ISSET(sd, &writeFdSet) != 0)
{
// This is used to regulate the rate
......@@ -435,8 +436,7 @@ int main(int argc, char *argv[])
if(rc < 0)
{
printf("Blocked in send = %d\n",errno);
exit(1);
printf("WARNING:Blocked in send = %d\n",errno);
}
else
{
......@@ -451,7 +451,7 @@ int main(int argc, char *argv[])
// for reading.
FD_SET(sd, &readFdSet);
select(1024, &readFdSet, NULL, NULL,&selectTimeout);
select(sd + 1, &readFdSet, NULL, NULL,&selectTimeout);
if(FD_ISSET(sd, &readFdSet) != 0)
{
......
......@@ -16,37 +16,49 @@ void UdpMaxDelaySensor::localSend(char *packetData, int Len,int overheadLen, uns
void UdpMaxDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp)
{
int minSize = 1 + sizeof(unsigned int) + sizeof(unsigned long long);
unsigned long long tmpMaxDelay = maxDelay;
if(Len < minSize)
{
cout << "Error: UDP packet data sent to MaxDelaySensor::localAck was less than the "
" required minimum "<< minSize << " bytes\n";
udpStateInfo.ackError = true;
return;
}
// Something went wrong with this packet - either the packet was not
// the minimum size or it was a re-ordered ACK - don't do anything
// with it - just return.
if( udpStateInfo.ackError == true )
return;
int numRedunAcks = static_cast<int>(packetData[0]);
vector<UdpPacketInfo * >::iterator vecIterator;
unsigned int seqNum = *(unsigned int *)(packetData + 1);
unsigned long long oneWayDelay;
unsigned long long oneWayQueueDelay;
bool eventFlag = false;
vecIterator = find_if(udpStateInfo.recentSentPackets.begin(), udpStateInfo.recentSentPackets.end(), bind2nd(equalSeqNum(), seqNum));
oneWayDelay = (timeStamp - (*vecIterator)->timeStamp)/2;
// Find the one way RTT for this packet.
oneWayQueueDelay = (timeStamp - (*vecIterator)->timeStamp)/2;
// Scale the value of one way RTT, so that it is correct for a transmission
// size of 1500 bytes.
oneWayQueueDelay = ( oneWayQueueDelay )*1500 / (overheadLen + Len + 1);
oneWayDelay = ( oneWayDelay )*1500 / (Len + 1);
// Find the queuing delay for this packet, by subtracting the
// one way minimum delay from the above value.
oneWayQueueDelay = oneWayQueueDelay - udpStateInfo.minDelay;
// Set this as the new maximum one way delay.
if(oneWayDelay > tmpMaxDelay)
// Set this as the new maximum one way queuing delay.
if(oneWayQueueDelay > maxDelay)
{
eventFlag = true;
tmpMaxDelay = oneWayDelay;
maxDelay = oneWayQueueDelay;
}
// Send an event message to the monitor to change the value of maximum one way delay.
maxDelay = tmpMaxDelay - udpStateInfo.minDelay;
if(udpStateInfo.packetLoss != 0 || eventFlag == true)
if(eventFlag == true)
{
// Report the maximum delay
cout << "New Max Delay = " << maxDelay << "\n";
......
......@@ -22,9 +22,17 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
{
cout << "Error: UDP packet data sent to MinDelaySensor::localAck was less than the "
" required minimum "<< minSize << " bytes\n";
udpStateInfo.ackError = true;
return;
}
// Something went wrong with this packet - either the packet was not
// the minimum size or it was a re-ordered ACK - don't do anything
// with it - just return.
if( udpStateInfo.ackError == true )
return;
int numRedunAcks = static_cast<int>(packetData[0]);
vector<UdpPacketInfo * >::iterator vecIterator;
unsigned int seqNum = *(unsigned int *)(packetData + 1);
......@@ -33,26 +41,26 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
vecIterator = find_if(udpStateInfo.recentSentPackets.begin(), udpStateInfo.recentSentPackets.end(), bind2nd(equalSeqNum(), seqNum));
// Calculate the one way delay as half of RTT.
oneWayDelay = (timeStamp - (*vecIterator)->timeStamp)/2;
long minDelayBytes = 0;
// Calculate the delay for the maximum possibly sized packet.
oneWayDelay = ( oneWayDelay ) * 1500 / (Len + 1);
// Calculate the delay for the maximum sized packet.
oneWayDelay = ( oneWayDelay ) * 1500 / (overheadLen + Len + 1);
// Set this as the new minimum one way delay.
if(oneWayDelay < minDelay)
{
eventFlag = true;
minDelay = oneWayDelay;
// One byte was chopped off in the base sensor class.
// Add that to the packet length.
minDelayBytes = Len + 1;
}
int redunAckSize = sizeof(unsigned int) + sizeof(unsigned long);
int seqNumSize = sizeof(unsigned int);
// We should not be calculating the minimum delay based on the
// redundant ACKs - because we cannot exactly calculate their
// RTT values, from just the receiver timestamps.
/*
if(numRedunAcks > 0)
{
int i;
......@@ -69,18 +77,19 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
if(vecIterator != udpStateInfo.recentSentPackets.end())
{
oneWayDelay = (timeStamp - timeDiff - (*vecIterator)->timeStamp ) /2;
oneWayDelay = ( oneWayDelay ) * 1500 / ( (*vecIterator)->packetSize );
oneWayDelay = ( oneWayDelay ) * 1500 / ( (*vecIterator)->packetSize + overheadLen );
if(oneWayDelay > 0 && oneWayDelay < minDelay)
{
eventFlag = true;
minDelay = oneWayDelay;
minDelayBytes = (*vecIterator)->packetSize;
minDelayBytes = (*vecIterator)->packetSize + overheadLen;
}
}
}
}
*/
// Send an event message to the monitor to change the value of minimum one way delay.
if(eventFlag == true)
......@@ -88,5 +97,4 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
cout << "New Min delay = " << minDelay << "\n";
}
udpStateInfo.minDelay = minDelay;
udpStateInfo.minDelayBytes = minDelayBytes;
}
......@@ -3,7 +3,7 @@
class UdpPacketInfo{
public:
UdpPacketInfo::UdpPacketInfo(unsigned int, unsigned int, unsigned long long, bool);
explicit UdpPacketInfo::UdpPacketInfo(unsigned int, unsigned int, unsigned long long, bool);
unsigned int seqNum;
unsigned int packetSize;
unsigned long long timeStamp;
......
......@@ -11,12 +11,16 @@ UdpPacketSensor::UdpPacketSensor(UdpState &udpStateVal)
void UdpPacketSensor::localSend(char *packetData, int Len, int overheadLen, unsigned long long timeStamp)
{
int minSize = 2*sizeof(unsigned int);
if(Len < minSize)
{
cout << "Error: UDP packet data sent to PacketSensor::localSend was less than the "
" required minimum "<< minSize << " bytes\n";
udpStateInfo.sendError = true;
return;
}
udpStateInfo.sendError = false;
unsigned int seqNum = *(unsigned int *)(packetData);
unsigned int packetSize = *(unsigned int *)(packetData + sizeof(unsigned int));
bool isFastPacket = false;
......@@ -30,16 +34,6 @@ void UdpPacketSensor::localSend(char *packetData, int Len, int overheadLen, unsi
sendTimeDelta = timeStamp - lastPacketTime;
lastPacketTime = timeStamp;
if(sendTimeDelta < udpStateInfo.minDelay)
isFastPacket = 1;
// We did not receive an ACK back, so we dont know the minimum
// one way delay. Treat all packets as fast packets until we
// find out the min. delay - this lowers the throughput a bit
// in case of packet loss if the packets were not being sent
// faster than min delay.
if(udpStateInfo.minDelay == 0)
isFastPacket = 1;
}
if(! sentPacketList.empty())
sentPacketList.back()->lastTimeDiff = sendTimeDelta;
......@@ -50,29 +44,15 @@ void UdpPacketSensor::localSend(char *packetData, int Len, int overheadLen, unsi
void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsigned long long timeStamp)
{
int minSize = 1 + sizeof(unsigned int) + sizeof(unsigned long long);
int i;
// Remove the old state information.
for(i = 0;i < udpStateInfo.recentSentPackets.size(); i++)
delete udpStateInfo.recentSentPackets[i];
udpStateInfo.recentSentPackets.clear();
udpStateInfo.packetLoss = 0;
udpStateInfo.fastPacketLoss = 0;
udpStateInfo.lostPacketDelay = 0;
udpStateInfo.lastSentTime = (ULONG_LONG_MAX);
if(Len < minSize)
{
cout << "Error: UDP packet data sent to PacketSensor::localAck was less than the "
" minimum "<< minSize << " bytes\n";
udpStateInfo.ackError = true;
return;
}
int redunAckSize = sizeof(unsigned int) + sizeof(unsigned long);
int numRedunAcks = static_cast<int>(packetData[0]);
unsigned int seqNum = *(unsigned int *)(packetData + 1);
// Find the entry for the packet this ACK is acknowledging, and
......@@ -85,9 +65,25 @@ void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsig
{
cout << "ERROR: Unacked packet list is incorrect Or incorrect"
"acknowledgement received for seqNum = "<<seqNum<<" in PacketSensor::localAck\n";
udpStateInfo.ackError = true;
return;
}
udpStateInfo.ackError = false;
int i;
// Remove the old state information.
for(i = 0;i < udpStateInfo.recentSentPackets.size(); i++)
delete udpStateInfo.recentSentPackets[i];
udpStateInfo.recentSentPackets.clear();
udpStateInfo.packetLoss = 0;
udpStateInfo.fastPacketLoss = 0;
udpStateInfo.lostPacketDelay = 0;
udpStateInfo.lastSentTime = (ULONG_LONG_MAX);
int redunAckSize = sizeof(unsigned int) + sizeof(unsigned long);
int numRedunAcks = static_cast<int>(packetData[0]);
// Store an iterator to the current seqNum being acknowledge, and delete it at the end.
list<UdpPacketInfo * >::iterator curPacketIterator = listIterator;
......@@ -106,7 +102,6 @@ void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsig
// Check whether the packet that this redundant ACK refers to exists
// in our list of sent ( but unacked ) packets. It might not exist
// if its ACK was not lost earlier.
//listIterator = find_if(sentPacketList.begin(), sentPacketList.end(), bind2nd(equalSeqNum(), redunSeqNum));
listIterator = find_if(sentPacketList.begin(), curPacketIterator, bind2nd(equalSeqNum(), redunSeqNum));
// An unacked packet exists with this sequence number, delete it
......@@ -132,18 +127,15 @@ void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsig
// Find out how many packets were lost.
listIterator = find_if(sentPacketList.begin(), sentPacketList.end(), bind2nd(lessSeqNum(), seqNum ));
listIterator = find_if(sentPacketList.begin(), curPacketIterator, bind2nd(lessSeqNum(), seqNum ));
if(listIterator != sentPacketList.end())
if( (listIterator != sentPacketList.end()) && (listIterator != curPacketIterator ))
{
do{
if( (*listIterator)->timeStamp < udpStateInfo.lastSentTime)
udpStateInfo.lastSentTime = (*listIterator)->timeStamp;
if( (*listIterator)->isFastPacket)
udpStateInfo.fastPacketLoss++;
udpStateInfo.lostPacketDelay += (*listIterator)->lastTimeDiff;
delete (*listIterator);
......
......@@ -9,7 +9,7 @@
using namespace std;
class UdpPacketInfo;
//class equalSeqNum;
class equalSeqNum;
class UdpSensor;
class UdpPacketSensor:public UdpSensor{
......
......@@ -24,6 +24,7 @@ struct UdpState{
unsigned long long lostPacketDelay;
long minDelayBytes;
bool sendError, ackError;
};
class equalSeqNum:public binary_function<const UdpPacketInfo * , unsigned int, bool> {
......
#include "UdpThroughputSensor.h"
UdpThroughputSensor::UdpThroughputSensor(UdpState &udpStateVal, ofstream &outStreamVal)
: lastAckTime(-1),
UdpThroughputSensor::UdpThroughputSensor(UdpState &udpStateVal, std::ofstream &outStreamVal)
: lastAckTime(0),
throughputKbps(0.0),
udpStateInfo(udpStateVal),
outStream(outStreamVal)
{
udpStateInfo.minAckTimeDiff = 999999999;
}
......@@ -16,44 +15,51 @@ void UdpThroughputSensor::localSend(char *packetData, int Len, int overheadLen,
}
void UdpThroughputSensor::localAck(char *packetData, int Len, int overheadLen, unsigned long long timeStamp)
void UdpThroughputSensor::localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp)
{
int minSize = 1 + sizeof(unsigned int) + sizeof(unsigned long long);
if(Len < minSize )
if(Len < minSize)
{
cout << "Error: UDP packet data sent to ThroughputSensor::localAck was less than the "
" required minimum "<< minSize << " bytes\n";
" required minimum "<< minSize << " bytes\n";
udpStateInfo.ackError = true;
return;
}
// Something went wrong with this packet - either the packet was not
// the minimum size or it was a re-ordered ACK - don't do anything
// with it - just return.
if( udpStateInfo.ackError == true )
return;
int redunAckSize = sizeof(unsigned int) + sizeof(unsigned long);
int seqNumSize = sizeof(unsigned int);
// Find out how many redundant ACKs this packet is carrying - 0 to 3.
int numRedunAcks = static_cast<int>(packetData[0]);
packetData++;
int numThroughputAcks = 1;
double avgThroughput = 0;
unsigned long long currentAckTimeStamp = *(unsigned long long *)(packetData + 1 + sizeof(unsigned int));
// This is the timestamp at the receiver, when the original packet was received.
unsigned long long currentAckTimeStamp = *(unsigned long long *)(packetData + sizeof(unsigned int));
if(lastAckTime == -1)
// This is the first ACK we have seen, store its receiver timestamp
// and return, we cannot calculate throughput from just one ACK - at least 2.
if(lastAckTime == 0)
{
lastAckTime = currentAckTimeStamp;
return;
}
unsigned int seqNum;
seqNum = *(unsigned int *)(packetData + 1);
unsigned int seqNum = *(unsigned int *)(packetData);
unsigned long ackTimeDiff = currentAckTimeStamp - lastAckTime;
unsigned long timeDiff = 0;
vector<UdpPacketInfo * >::iterator vecIterator;
long dataSize = 0;
unsigned long long oneWayDelay = 0;
unsigned long long totalDelay = 0;
vecIterator = find_if(udpStateInfo.recentSentPackets.begin(), udpStateInfo.recentSentPackets.end(), bind2nd(equalSeqNum(), seqNum));
//oneWayDelay = (timeStamp - (*vecIterator)->timeStamp)/2;
oneWayDelay = (timeStamp - udpStateInfo.lastSentTime)/2;
totalDelay = oneWayDelay;
// Average the throughput over all the packets being acknowledged.
if(numRedunAcks > 0)
......@@ -72,34 +78,43 @@ void UdpThroughputSensor::localAck(char *packetData, int Len, int overheadLen, u
{
// Calculate throughput for the packet being acked by
// the redundant ACK.
dataSize += (*vecIterator)->packetSize;
numThroughputAcks++;
timeDiff = *(unsigned long *)(packetData + minSize + i*redunAckSize + seqNumSize);
avgThroughput += 8000000.0*( static_cast<double> ( (*vecIterator)->packetSize + overheadLen )) / ( static_cast<double>(ackTimeDiff - timeDiff)*1024.0 );
ackTimeDiff = timeDiff;
}
}
}
// Calculate the throughput for the current packet being ACKed.
vecIterator = find_if(udpStateInfo.recentSentPackets.begin(), udpStateInfo.recentSentPackets.end(), bind2nd(equalSeqNum(), seqNum));
dataSize += ( (*vecIterator)->packetSize + overheadLen );
throughputKbps = 8000000.0*( static_cast<double> (dataSize )) / ( static_cast<double>(totalDelay)*1024.0 );
avgThroughput += 8000000.0*( static_cast<double> ((*vecIterator)->packetSize + overheadLen )) / ( static_cast<double>(ackTimeDiff)*1024.0 );
throughputKbps = avgThroughput / (static_cast<double> (numThroughputAcks) );
// Send a message to the monitor with the new bandwidth.
if(udpStateInfo.packetLoss == 0)
{
// Send this available bandwidth as a tentative value.
// To be used for dummynet events only if it is greater
// than the last seen value.
cout << "Tentative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<", ackTimeDiff = "<<ackTimeDiff<<"\n";
outStream << "TIME="<<timeStamp<<",TENTATIVE="<<throughputKbps<<endl;
cout << "Tentative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<"acktimeDiff = "<<ackTimeDiff<<"\n";
outStream << "TIME="<<timeStamp<<",TENTATIVE="<<throughputKbps<<endl;
}
else
{
// Send this as the authoritative available bandwidth value.
cout << "Authoritative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<", ackTimeDiff ="<<ackTimeDiff<<"\n";
cout << "Authoritative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<"ackTimeDiff = "<<ackTimeDiff<<"\n";
outStream << "TIME="<<timeStamp<<",AUTHORITATIVE="<<throughputKbps<<endl;
}
// Save the receiver timestamp of this ACK packet, so that we can
// use for calculating throughput for the next ACK packet.
lastAckTime = currentAckTimeStamp;
}
......@@ -15,7 +15,7 @@ class UdpThroughputSensor:public UdpSensor{
void localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
private:
long long lastAckTime;
unsigned long long lastAckTime;
double throughputKbps;
UdpState &udpStateInfo;
ofstream &outStream;
......
......@@ -14,4 +14,4 @@
# NOTE: The UdpServer needs to be restarted before running the client for a second time.
sudo ./UdpClient eth1 10.1.2.2 udpnode1 1000 958 4000000
sudo ./UdpClient eth1 10.1.1.2 udpnode2 200000 958 500000
......@@ -24,6 +24,7 @@
#define LOCAL_SERVER_PORT 1500
#define MAX_MSG 1524
#define SNAPLEN 128
pcap_t *pcapDescriptor = NULL;
......@@ -46,6 +47,7 @@ int sd, rc, n, flags;
socklen_t cliLen;
struct sockaddr_in cliAddr, servAddr;
unsigned long long lastAckTime = 0;
std::ofstream outFile;
unsigned long long getPcapTimeMicro(const struct timeval *tp)
{
......@@ -204,6 +206,7 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// will be a combination of code below and that in UdpClient.
{
unsigned int packetSeqNum = *(unsigned int *)(dataPtr + 1) ;
int overhead = ipPacket->ip_hl*4 + 8 + 14 + 2;
//printf("Data being received = %c, %u\n", *(unsigned char *)(dataPtr), *(unsigned int *)(dataPtr + 1));
// If this sequence number is greater than the last sequence number
......@@ -217,6 +220,7 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
memcpy(&appAck[2], &packetSeqNum, sizeof(unsigned int));
milliSec = getPcapTimeMicro(&pcap_info->ts);
outFile << "TIME="<<milliSec<<",SIZE="<<udpLen - 8 + overhead<<std::endl;
if(lastAckTime == 0)
lastAckTime = milliSec;
else
......@@ -392,7 +396,7 @@ void init_pcap(char *interface)
pcap_lookupnet(interface, &netp, &maskp, errBuf);
pcapDescriptor = pcap_open_live(interface, BUFSIZ, 0, 0, errBuf);
pcapDescriptor = pcap_open_live(interface, SNAPLEN, 0, 0, errBuf);
localAddress.s_addr = netp;
printf("IP addr = %s\n", inet_ntoa(localAddress));
......@@ -451,8 +455,6 @@ int main(int argc, char *argv[])
cliLen = sizeof(cliAddr);
std::ofstream outFile;
outFile.open("Throughput.log", std::ios::out);
/* server infinite loop */
......
......@@ -25,7 +25,7 @@ for line in inFile:
else: