Commit a1cfdc36 authored by Pramod R Sanaga's avatar Pramod R Sanaga

1) Added a UdpSensorList class.

2) Replaced gettimeofday calls with TSC register reads.
3) Removed all recvfrom calls - no overhead for those calls & copying
packets to user space - this does not adversely affect performance.
4) More graphs!! and streamlined error/warning messages to be put into a single
log file.
parent 319e7ac5
......@@ -163,6 +163,24 @@ 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.
Optimizations:
--------------
1) The UdpClient application sends packets at a fixed rate specified at the
command line. In order to keep of the time, gettimeofday() can be used. But,
on planet lab using gettimeofday() may cause the program to be scheduled
out because it is a system call. Instead, the sending times are now
being calculated by reading the values of the TSC register. Now,
the deviation between when we wish to send a packet and we actually send
it is around 2 ms against the 10+ ms when using gettimeofday.
2) Since we capture and process all UDP packets using libpcap, there is no
need to make recvfrom() calls, either at the sender or at the receiver. Those
calls have now been removed and we will not incur the overhead of the system calls
and the time to copy the packets to user space. I ran the application in a controlled
emulab environment and did not observe any increase in CPU usage when all the received
UDP packets were being dropped by the kernel ( due to full socket receive buffer ).
......
......@@ -10,7 +10,8 @@ OBJECTS=${COMPILE_DIR}/UdpClient.o \
${COMPILE_DIR}/UdpMaxDelaySensor.o \
${COMPILE_DIR}/UdpThroughputSensor.o \
${COMPILE_DIR}/UdpPacketInfo.o \
${COMPILE_DIR}/UdpSensor.o
${COMPILE_DIR}/UdpSensor.o \
${COMPILE_DIR}/UdpSensorList.o
COMMON_INCLUDES=UdpLibs.h \
......@@ -40,6 +41,9 @@ ${COMPILE_DIR}/UdpPacketInfo.o: UdpPacketInfo.cc UdpPacketInfo.h ${COMMON_INCLU
${COMPILE_DIR}/UdpSensor.o: UdpSensor.cc UdpSensor.h ${COMMON_INCLUDES}
${CC} -c ${CFLAGS} -o $@ $<
${COMPILE_DIR}/UdpSensorList.o: UdpSensorList.cc UdpSensorList.h ${COMMON_INCLUDES}
${CC} -c ${CFLAGS} -o $@ $<
clean:
rm -f ${COMPILE_DIR}/*.o ${EXECUTABLE}
This diff is collapsed.
......@@ -20,7 +20,9 @@ namespace globalConsts {
const static int redunAckSize = 2*USHORT_INT_SIZE + ULONG_LONG_SIZE;
const static int seqNumSize = USHORT_INT_SIZE;
const static int minAckPacketSize = 1 + 2*USHORT_INT_SIZE + ULONG_LONG_SIZE;
const static int minAckPacketSize = 1 + 2*USHORT_INT_SIZE + 2*ULONG_LONG_SIZE;
}
enum {UDP_PACKET_SENSOR, UDP_THROUGHPUT_SENSOR, UDP_MINDELAY_SENSOR, UDP_MAXDELAY_SENSOR};
#endif
#include "UdpMaxDelaySensor.h"
UdpMaxDelaySensor::UdpMaxDelaySensor(UdpState &udpStateVal, ofstream &outStreamVal)
UdpMaxDelaySensor::UdpMaxDelaySensor(UdpState &udpStateVal, ofstream &logStreamVal)
: maxDelay(0),
udpStateInfo(udpStateVal),
outStream(outStreamVal)
logStream(logStreamVal)
{
}
UdpMaxDelaySensor::~UdpMaxDelaySensor()
{
}
......@@ -18,7 +23,7 @@ void UdpMaxDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
{
if(Len < globalConsts::minAckPacketSize)
{
cout << "Error: UDP packet data sent to MaxDelaySensor::localAck was less than the "
logStream << "ERROR::UDP packet data sent to MaxDelaySensor::localAck was less than the "
" required minimum "<< globalConsts::minAckPacketSize << " bytes\n";
return;
}
......@@ -30,7 +35,7 @@ void UdpMaxDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
unsigned short int seqNum = *(unsigned short int *)(packetData + 1);
unsigned short int echoedPacketSize = *(unsigned short int *)(packetData + 1 + globalConsts::USHORT_INT_SIZE);
unsigned long long echoedTimestamp = *(unsigned long long *)(packetData + 1 + 2*globalConsts::USHORT_INT_SIZE);
unsigned long long echoedTimestamp = *(unsigned long long *)(packetData + 1 + 2*globalConsts::USHORT_INT_SIZE + globalConsts::ULONG_LONG_SIZE);
unsigned long long oneWayQueueDelay;
bool eventFlag = false;
......@@ -73,9 +78,10 @@ void UdpMaxDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
if(eventFlag == true)
{
// Report the maximum delay
cout << "New Max Delay = " << maxDelay << "\n";
logStream << "VALUE::New Max Delay = " << maxDelay << "\n";
}
outStream << "MAXD:TIME="<<timeStamp<<",MAXD="<<maxDelay<<endl;
logStream << "MAXD:TIME="<<timeStamp<<",MAXD="<<maxDelay<<endl;
logStream << "ACTUAL_MAXD:TIME="<<timeStamp<<",ACTUAL_MAXD="<<oneWayQueueDelay<<endl;
udpStateInfo.maxDelay = maxDelay;
}
......@@ -10,14 +10,17 @@ class UdpSensor;
class UdpMaxDelaySensor:public UdpSensor{
public:
explicit UdpMaxDelaySensor(UdpState &udpStateVal, ofstream &outStreamVal);
explicit UdpMaxDelaySensor(UdpState &udpStateVal, ofstream &logStreamVal);
~UdpMaxDelaySensor();
void localSend(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
void localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
private:
unsigned long long maxDelay;
UdpState &udpStateInfo;
ofstream &outStream;
ofstream &logStream;
};
#endif
#include "UdpMinDelaySensor.h"
UdpMinDelaySensor::UdpMinDelaySensor(UdpState &udpStateVal, ofstream &outStreamVal)
UdpMinDelaySensor::UdpMinDelaySensor(UdpState &udpStateVal, ofstream &logStreamVal)
: minDelay(ULONG_LONG_MAX),
udpStateInfo(udpStateVal),
outStream(outStreamVal)
logStream(logStreamVal)
{
}
UdpMinDelaySensor::~UdpMinDelaySensor()
{
}
......@@ -19,7 +24,7 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
{
if(Len < globalConsts::minAckPacketSize)
{
cout << "Error: UDP packet data sent to MinDelaySensor::localAck was less than the "
logStream << "ERROR::UDP packet data sent to MinDelaySensor::localAck was less than the "
" required minimum "<< globalConsts::minAckPacketSize << " bytes\n";
return;
}
......@@ -31,7 +36,7 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
unsigned short int seqNum = *(unsigned short int *)(packetData + 1);
unsigned short int echoedPacketSize = *(unsigned short int *)(packetData + 1 + globalConsts::USHORT_INT_SIZE);
unsigned long long echoedTimestamp = *(unsigned long long *)(packetData + 1 + 2*globalConsts::USHORT_INT_SIZE);
unsigned long long echoedTimestamp = *(unsigned long long *)(packetData + 1 + 2*globalConsts::USHORT_INT_SIZE + globalConsts::ULONG_LONG_SIZE);
unsigned long long oneWayDelay;
bool eventFlag = false;
......@@ -73,8 +78,8 @@ void UdpMinDelaySensor::localAck(char *packetData, int Len,int overheadLen, unsi
// Send an event message to the monitor to change the value of minimum one way delay.
if(eventFlag == true)
{
cout << "New Min delay = " << minDelay << "\n";
logStream << "VALUE::New Min delay = " << minDelay << "\n";
}
outStream << "MIND:TIME="<<timeStamp<<",MIND="<<minDelay<<endl;
logStream << "MIND:TIME="<<timeStamp<<",MIND="<<minDelay<<endl;
udpStateInfo.minDelay = minDelay;
}
......@@ -10,14 +10,17 @@ class UdpSensor;
class UdpMinDelaySensor:public UdpSensor{
public:
explicit UdpMinDelaySensor(UdpState &udpStateVal, ofstream &outStreamVal);
explicit UdpMinDelaySensor(UdpState &udpStateVal, ofstream &logStreamVal);
~UdpMinDelaySensor();
void localSend(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
void localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
private:
unsigned long long minDelay;
UdpState &udpStateInfo;
ofstream &outStream;
ofstream &logStream;
};
#endif
......@@ -11,3 +11,8 @@ UdpPacketInfo::UdpPacketInfo(unsigned short int seqVal,unsigned short int packet
{
}
UdpPacketInfo::~UdpPacketInfo()
{
}
......@@ -3,8 +3,10 @@
class UdpPacketInfo{
public:
UdpPacketInfo::UdpPacketInfo();
UdpPacketInfo::UdpPacketInfo(unsigned short int, unsigned short int, unsigned long long);
UdpPacketInfo();
UdpPacketInfo(unsigned short int, unsigned short int, unsigned long long);
~UdpPacketInfo();
unsigned short int seqNum;
unsigned short int packetSize;
unsigned long long timeStamp;
......
#include "UdpPacketSensor.h"
UdpPacketSensor::UdpPacketSensor(UdpState &udpStateVal)
UdpPacketSensor::UdpPacketSensor(UdpState &udpStateVal, ofstream &logStreamVal)
:udpStateInfo(udpStateVal),
lastSeenSeqNum(-1)
lastSeenSeqNum(-1),
logStream(logStreamVal)
{
}
......@@ -20,7 +21,7 @@ void UdpPacketSensor::localSend(char *packetData, int Len, int overheadLen, unsi
if(Len < minSize)
{
cout << "Error: UDP packet data sent to PacketSensor::localSend was less than the "
logStream << "ERROR::UDP packet data sent to PacketSensor::localSend was less than the "
" required minimum "<< minSize << " bytes\n";
return;
}
......@@ -43,6 +44,7 @@ void UdpPacketSensor::localSend(char *packetData, int Len, int overheadLen, unsi
sentPacketList.push_back(tmpPacketInfo);
}
udpStateInfo.libpcapSendLoss += (seqNum - lastSeenSeqNum - 1);
}
}
......@@ -60,7 +62,7 @@ void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsig
{
if(Len < globalConsts::minAckPacketSize)
{
cout << "Error: UDP packet data sent to PacketSensor::localAck was less than the "
logStream << "ERROR::UDP packet data sent to PacketSensor::localAck was less than the "
" minimum "<< globalConsts::minAckPacketSize << " bytes\n";
return;
}
......@@ -75,7 +77,7 @@ void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsig
if(listIterator == sentPacketList.end())
{
cout << "WARNING: Unknown seq number "<<seqNum<<" is being ACKed. "
logStream << "WARNING::Unknown seq number "<<seqNum<<" is being ACKed. "
"We might have received "
" a reordered ACK, which has already been ACKed using redundant ACKs .\n";
udpStateInfo.ackError = true;
......@@ -158,18 +160,21 @@ void UdpPacketSensor::localAck(char *packetData, int Len, int overheadLen, unsig
if( (listIterator != sentPacketList.end()) && (listIterator != curPacketIterator ))
{
logStream<<"STAT::Packet being ACKed = "<<seqNum<<endl;
do{
logStream<<"STAT::Lost packet seqnum = "<<(*listIterator).seqNum<<endl;
sentPacketList.erase(listIterator);
listIterator = sentPacketList.end();
udpStateInfo.packetLoss++;
udpStateInfo.totalPacketLoss++;
listIterator = find_if(sentPacketList.begin(), curPacketIterator, bind2nd(lessSeqNum(), seqNum ));
}
while( (listIterator != sentPacketList.end()) && (listIterator != curPacketIterator) );
logStream<<"STAT::Total packet loss = "<<udpStateInfo.totalPacketLoss<<"\n"<<endl;
}
sentPacketList.erase(curPacketIterator);
......
......@@ -16,7 +16,7 @@ class UdpPacketSensor:public UdpSensor{
public:
explicit UdpPacketSensor(UdpState &udpStateVal);
explicit UdpPacketSensor(UdpState &udpStateVal, ofstream &logStreamVal);
~UdpPacketSensor();
void localSend(char *packetData, int Len, int overheadLen, unsigned long long timeStamp);
void localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
......@@ -26,6 +26,7 @@ class UdpPacketSensor:public UdpSensor{
list<UdpPacketInfo> sentPacketList;
UdpState & udpStateInfo;
long lastSeenSeqNum;
ofstream &logStream;
};
......
......@@ -7,6 +7,11 @@ UdpSensor::UdpSensor()
}
UdpSensor::~UdpSensor()
{
}
void UdpSensor::capturePacket(char *packetData, int Len, int overheadLen, unsigned long long timeStamp)
{
if(Len < 1)
......@@ -24,4 +29,5 @@ void UdpSensor::capturePacket(char *packetData, int Len, int overheadLen, unsign
{
localAck( (packetData + 1), Len - 1,overheadLen, timeStamp );
}
}
......@@ -6,9 +6,15 @@
class UdpSensor{
public:
UdpSensor();
virtual ~UdpSensor();
void capturePacket(char *packetData, int Len, int overheadLen, unsigned long long timeStamp);
UdpSensor *next;
protected:
virtual void localSend(char *packetData, int Len, int overheadLen,unsigned long long timeStamp)=0;
virtual void localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp)=0;
void capturePacket(char *packetData, int Len, int overheadLen, unsigned long long timeStamp);
};
#endif
......@@ -14,14 +14,43 @@ class UdpState{
// sequence number, timestamp & size of the packet.
vector< UdpPacketInfo > recentSentPackets;
// Indicates the number of packets lost ( in a batch of 4 sent packets )
// Indicates the number of packets lost -
// updated whenever an ACK is received.
int packetLoss;
// This is the total number of packets lost till now for the connection.
int totalPacketLoss;
// Did we drop any packets in libpcap ?
// This number only indicates the number of sent packets that
// were dropped in pcap buffer - based on the differences between
// the sequence numbers seen.
int libpcapSendLoss;
unsigned long long minDelay;
unsigned long long maxDelay;
bool ackError, isAckFake;
UdpState()
:packetLoss(0),
totalPacketLoss(0),
libpcapSendLoss(0)
{
}
void reset()
{
packetLoss = 0;
totalPacketLoss = 0;
libpcapSendLoss = 0;
ackError = false;
isAckFake = false;
}
~UdpState()
{
// Remove any packets stored in the vector.
......
#include "UdpThroughputSensor.h"
UdpThroughputSensor::UdpThroughputSensor(UdpState &udpStateVal, std::ofstream &outStreamVal)
UdpThroughputSensor::UdpThroughputSensor(UdpState &udpStateVal, std::ofstream &logStreamVal)
: lastAckTime(0),
throughputKbps(0.0),
udpStateInfo(udpStateVal),
outStream(outStreamVal)
logStream(logStreamVal)
{
}
UdpThroughputSensor::~UdpThroughputSensor()
{
}
......@@ -19,7 +24,7 @@ void UdpThroughputSensor::localAck(char *packetData, int Len,int overheadLen, un
{
if(Len < globalConsts::minAckPacketSize )
{
cout << "Error: UDP packet data sent to ThroughputSensor::localAck was less than the "
logStream << "ERROR::UDP packet data sent to ThroughputSensor::localAck was less than the "
" required minimum "<< globalConsts::minAckPacketSize<< " bytes\n";
return;
}
......@@ -109,17 +114,17 @@ void UdpThroughputSensor::localAck(char *packetData, int Len,int overheadLen, un
// 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";
logStream << "VALUE::Tentative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<"acktimeDiff = "<<ackTimeDiff<<"\n";
outStream << "TPUT:TIME="<<timeStamp<<",TENTATIVE="<<throughputKbps<<endl;
outStream << "LOSS:TIME="<<timeStamp<<",LOSS=0"<<endl;
logStream << "TPUT:TIME="<<timeStamp<<",TENTATIVE="<<throughputKbps<<endl;
logStream << "LOSS:TIME="<<timeStamp<<",LOSS=0"<<endl;
}
else
{
// Send this as the authoritative available bandwidth value.
cout << "Authoritative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<"ackTimeDiff = "<<ackTimeDiff<<"\n";
outStream << "TPUT:TIME="<<timeStamp<<",AUTHORITATIVE="<<throughputKbps<<endl;
outStream << "LOSS:TIME="<<timeStamp<<",LOSS="<<udpStateInfo.packetLoss<<endl;
logStream << "VALUE::Authoritative bandwidth for seqNum = "<<seqNum<<", value = "<< throughputKbps <<"ackTimeDiff = "<<ackTimeDiff<<"\n";
logStream << "TPUT:TIME="<<timeStamp<<",AUTHORITATIVE="<<throughputKbps<<endl;
logStream << "LOSS:TIME="<<timeStamp<<",LOSS="<<udpStateInfo.packetLoss<<endl;
}
// Save the receiver timestamp of this ACK packet, so that we can
......
......@@ -10,7 +10,8 @@ class UdpSensor;
class UdpThroughputSensor:public UdpSensor{
public:
explicit UdpThroughputSensor(UdpState &udpStateVal, ofstream &outStreamVal);
explicit UdpThroughputSensor(UdpState &udpStateVal, ofstream &logStreamVal);
~UdpThroughputSensor();
void localSend(char *packetData, int Len, int overheadLen, unsigned long long timeStamp);
void localAck(char *packetData, int Len,int overheadLen, unsigned long long timeStamp);
......@@ -18,7 +19,7 @@ class UdpThroughputSensor:public UdpSensor{
unsigned long long lastAckTime;
double throughputKbps;
UdpState &udpStateInfo;
ofstream &outStream;
ofstream &logStream;
};
#endif
......@@ -11,6 +11,8 @@ lossFile = "Loss.log"
minDelayFile = "MinDelay.log"
maxDelayFile = "MaxDelay.log"
sendDeviationFile = "SendDeviation.log"
queueDelayFile = "QueueDelay.log"
messageFile = "Messages.log"
# And print out the bandwidth, packet loss, minimum delay and
# queue size into seperate files, so that they can be plotted
......@@ -21,6 +23,8 @@ outFileLoss = open(lossFile, 'w')
outFileMinD = open(minDelayFile, 'w')
outFileMaxD = open(maxDelayFile, 'w')
outFileSendDeviation = open(sendDeviationFile, 'w')
outFileQueueD = open(queueDelayFile, 'w')
outFileMessages = open(messageFile, 'w')
regExp = re.compile('^(\w*?):(\w*?)\=(\d*)\,(\w*?)\=([\d\.]*)')
......@@ -29,72 +33,84 @@ bandWidthBps = 0
throughputBps = 0
# Array indices, 0 - throughput, 1 - loss, 2 - minimum delay, 3 - queue size
# 4 - deviation in send times
initTimeArray = [0,0,0,0,0]
timeDiffArray = [0,0,0,0,0]
initFlagsArray = [0,0,0,0,0]
# 4 - deviation in send times, 5 - actual queuing delay per packet
initTimeArray = [0,0,0,0,0,0]
timeDiffArray = [0,0,0,0,0,0]
initFlagsArray = [0,0,0,0,0,0]
for line in inFile:
match = regExp.match(line)
if match.group(1) == 'TPUT':
if initFlagsArray[0] == 0:
initTimeArray[0] = int(match.group(3))
timeDiffArray[0] = 0
initFlagsArray[0] = 1
else:
timeDiffArray[0] = int(match.group(3)) - initTimeArray[0]
if match.group(4) == 'AUTHORITATIVE':
availBandwidth = float(match.group(5))
elif match.group(4) == 'TENTATIVE':
if float(match.group(5)) > availBandwidth:
availBandwidth = float(match.group(5))
if match:
if match.group(1) == 'TPUT':
if initFlagsArray[0] == 0:
initTimeArray[0] = int(match.group(3))
timeDiffArray[0] = 0
initFlagsArray[0] = 1
else:
timeDiffArray[0] = int(match.group(3)) - initTimeArray[0]
bandWidthBps = 1024*availBandwidth / ( 8 )
throughputBps = 1024* ( float(match.group(5) ) ) / ( 8 )
outFileBandwidth.write(str(timeDiffArray[0]) + " " + str(bandWidthBps) + "\n" )
outFileThroughput.write(str(timeDiffArray[0]) + " " + str(throughputBps) + "\n" )
elif match.group(1) == 'LOSS':
if initFlagsArray[1] == 0:
initTimeArray[1] = int(match.group(3))
timeDiffArray[1] = 0
initFlagsArray[1] = 1
else:
timeDiffArray[1] = int(match.group(3)) - initTimeArray[1]
outFileLoss.write(str(timeDiffArray[1]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'MIND':
if initFlagsArray[2] == 0:
initTimeArray[2] = int(match.group(3))
timeDiffArray[2] = 0
initFlagsArray[2] = 1
else:
timeDiffArray[2] = int(match.group(3)) - initTimeArray[2]
outFileMinD.write(str(timeDiffArray[2]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'MAXD':
if initFlagsArray[3] == 0:
initTimeArray[3] = int(match.group(3))
timeDiffArray[3] = 0
initFlagsArray[3] = 1
else:
timeDiffArray[3] = int(match.group(3)) - initTimeArray[3]
outFileMaxD.write(str(timeDiffArray[3]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'SendDeviation':
if initFlagsArray[4] == 0:
initTimeArray[4] = int(match.group(3))
timeDiffArray[4] = 0
initFlagsArray[4] = 1
else:
timeDiffArray[4] = int(match.group(3)) - initTimeArray[4]
outFileSendDeviation.write(str(timeDiffArray[4]) + " " + match.group(5) + "\n" )
if match.group(4) == 'AUTHORITATIVE':
availBandwidth = float(match.group(5))
elif match.group(4) == 'TENTATIVE':
if float(match.group(5)) > availBandwidth:
availBandwidth = float(match.group(5))
bandWidthBps = 1024*availBandwidth / ( 8 )
throughputBps = 1024* ( float(match.group(5) ) ) / ( 8 )
outFileBandwidth.write(str(timeDiffArray[0]) + " " + str(bandWidthBps) + "\n" )
outFileThroughput.write(str(timeDiffArray[0]) + " " + str(throughputBps) + "\n" )
elif match.group(1) == 'LOSS':
if initFlagsArray[1] == 0:
initTimeArray[1] = int(match.group(3))
timeDiffArray[1] = 0
initFlagsArray[1] = 1
else:
timeDiffArray[1] = int(match.group(3)) - initTimeArray[1]
outFileLoss.write(str(timeDiffArray[1]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'MIND':
if initFlagsArray[2] == 0:
initTimeArray[2] = int(match.group(3))
timeDiffArray[2] = 0
initFlagsArray[2] = 1
else:
timeDiffArray[2] = int(match.group(3)) - initTimeArray[2]
outFileMinD.write(str(timeDiffArray[2]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'MAXD':
if initFlagsArray[3] == 0:
initTimeArray[3] = int(match.group(3))
timeDiffArray[3] = 0
initFlagsArray[3] = 1
else:
timeDiffArray[3] = int(match.group(3)) - initTimeArray[3]
outFileMaxD.write(str(timeDiffArray[3]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'SendDeviation':
if initFlagsArray[4] == 0:
initTimeArray[4] = int(match.group(3))
timeDiffArray[4] = 0
initFlagsArray[4] = 1
else:
timeDiffArray[4] = int(match.group(3)) - initTimeArray[4]
outFileSendDeviation.write(str(timeDiffArray[4]) + " " + match.group(5) + "\n" )
elif match.group(1) == 'ACTUAL_MAXD':
if initFlagsArray[5] == 0:
initTimeArray[5] = int(match.group(3))
timeDiffArray[5] = 0
initFlagsArray[5] = 1
else:
timeDiffArray[5] = int(match.group(3)) - initTimeArray[5]
outFileQueueD.write(str(timeDiffArray[5]) + " " + match.group(5) + "\n" )
else:
outFileMessages.write(line)
......@@ -8,10 +8,11 @@
# Five - Size of the data part of the UDP packets.
# Six - The rate at which the packets should be sent ( bits per sec )
# This rate will also include the UDP, IP & ethernet headers along with the packet size.
# Seven - MHz of CPU clock frequency
# The client runs in an infinite while loop - so when no more data is being printed on
# screen, it is safe to kill it( Ctrl-C) and look at the results.
# NOTE: The UdpServer needs to be restarted before running the client for a second time.
sudo ./UdpClient eth0 10.1.1.2 node1 600 1470 200000
sudo ./UdpClient eth1 10.1.1.2 node1 1000 1470 750000 601
......@@ -50,6 +50,7 @@ int sd, rc, n, flags;
socklen_t cliLen;
struct sockaddr_in cliAddr, servAddr;
std::ofstream outFile;
int packetLoss;
namespace globalConsts {
......@@ -76,6 +77,8 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// Subtract eight bytes to account for the UDP header.
unsigned short udpLen = ntohs(udpHdr->len) - 8;
unsigned short int sourcePort = ntohs(udpHdr->source);
// The first byte of the data portion indicates whether this
// is a send packet(0) or an ACK packet(1)
unsigned char packetType = *(unsigned char *)(dataPtr);
......@@ -92,7 +95,6 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// will be a combination of code below and that in UdpClient.
{
unsigned short int packetSeqNum = *(unsigned short int *)(dataPtr + 1) ;
std::cout<<"Received seq no = "<<packetSeqNum<<std::endl;
// Calculate the header overhead, IP, 8 bytes for UDP, 14 + 4 for ethernet
int overhead = ipPacket->ip_hl*4 + 8 + 14 + 4;
......@@ -111,6 +113,16 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// TODO:Take wrap around into account.
if(packetSeqNum > curSeqNum)
{
if(packetSeqNum > (curSeqNum + 1))
{
/*
std::cout<<"Packet being ACKed = "<<packetSeqNum<<std::endl;
packetLoss += (packetSeqNum - curSeqNum - 1);
std::cout<<"Forward packet loss = "<<packetLoss<<std::endl;
for(int k = 1;k < packetSeqNum - curSeqNum; k++)
std::cout<<"Lost packet seqNum = "<<curSeqNum + 1<<"\n"<<std::endl;
*/
}
// Indicate that this is an ACK packet.
appAck[0] = '1';
......@@ -123,6 +135,10 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// Get the timestamp of when this packet was received by libpcap.
milliSec = getPcapTimeMicro(&pcap_info->ts);
memcpy(&appAck[2 + 2*globalConsts::USHORT_INT_SIZE], &milliSec, globalConsts::ULONG_LONG_SIZE);
// Echo the sender timestamp received in the original packet.
memcpy(&appAck[2 + 2*globalConsts::USHORT_INT_SIZE + globalConsts::ULONG_LONG_SIZE], &senderTimestamp, globalConsts::ULONG_LONG_SIZE);
outFile << "TIME="<<milliSec<<",SIZE="<<udpLen + overhead<<std::endl;
// Include the sequence numbers, and ACK times of at least the last
......@@ -134,8 +150,9 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
unsigned long long timeDiff = 0;
// Size of each redundant ACK - 2 bytes for sequence number + 2 bytes
// for the packet size + 8 bytes for timestamp.
int ackSize = 2*globalConsts::USHORT_INT_SIZE + globalConsts::ULONG_LONG_SIZE;
// for the packet size + 8 bytes for receiver timestamp + 8 bytes for
// echoing the sender timestamp.
int ackSize = 2*globalConsts::USHORT_INT_SIZE + 2*globalConsts::ULONG_LONG_SIZE;
if(queueStartPtr == -1 && queueEndPtr == -1)
{
......@@ -151,7 +168,7 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// This is the packet size that is needed to hold the minimum
// number of redundant ACKs + sequence number being ACKed + other data.
ackLength = minimumAcks*ackSize + 2*globalConsts::USHORT_INT_SIZE + globalConsts::ULONG_LONG_SIZE + 2;
ackLength = minimumAcks*ackSize + 2*globalConsts::USHORT_INT_SIZE + 2*globalConsts::ULONG_LONG_SIZE + 2;
// Check to see if the original packet size can accommodate more
// than 3 redundant ACKs.
......@@ -177,7 +194,7 @@ void handleUDP(struct pcap_pkthdr const *pcap_info, struct udphdr const *udpHdr,
// because our redundant ACK size is 12. These extra bytes
// will be accounted for by the step below which makes the
// packet being sent the same size as the received packet.