Commit 4ac9f13c authored by Pramod R Sanaga's avatar Pramod R Sanaga

First step in adding/integrating udp support into magent - added

the packet, throughput, min delay & max delay sensors and code
for doing udp packet writes with sequence number, packet size & sender
timestamps embedded in the data segment.
parent d9c384e7
......@@ -78,6 +78,25 @@ void KernelTcp::connect(PlanetOrder & planet)
{
// PRAMOD: Insert any additional setup code for UDP connections here.
state = CONNECTED;
// Udp - CHANGES - Begin
udpCurSeqNum = 0;
// Create a datagram socket and bind it the local address.
if(peersock == -1)
{
peersock = socket(AF_INET, SOCK_DGRAM, 0);
if(peersock < 0)
{
logWrite(ERROR, "Could not create a datagram socket in KernelTcp::connect");
}
udpLocalAddr.sin_family = AF_INET;
udpLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(peersock, (struct sockaddr *)&udpLocalAddr, sizeof(udpLocalAddr));
}
// Udp - CHANGES - End
}
if (state == DISCONNECTED)
{
......@@ -320,7 +339,79 @@ int KernelTcp::writeUdpMessage(int size, WriteResult & result)
// put the localport in host order in result.planet.localPort
// set result.bufferFull to false (UDP 'buffers' are never full)
// set result.isConnected to true (UDP 'connections' are always connected)
return writeTcpMessage(size, result);
if(size < global::udpMinSendPacketSize)
size = global::udpMinSendPacketSize;
// Put the sequence number of the packet.
unsigned short networkOrder_udpCurSeqNum = htons(udpCurSeqNum);
memcpy(&udpPacketBuffer[0],&networkOrder_udpCurSeqNum, global::USHORT_INT_SIZE);
// Copy the size of the packet.. This can be used
// by the sensors in case they miss this packet
// because of libpcap buffer overflow.
// The size of the packet & its timestamp at the
// sender are echoed in the ACKs.
unsigned short networkOrder_size = htons(size);
memcpy(&udpPacketBuffer[global::USHORT_INT_SIZE],&networkOrder_size, global::USHORT_INT_SIZE);
// Copy the timestamp of when this packet is being sent.
// This timestamp will not be as accurate as
// the one captured by libpcap, but can be
// used as a fallback option in case we miss
// this packet because of a libpcap buffer overflow.
unsigned long long curTime = getCurrentTime().toMicroseconds();
curTime = htonll(curTime);
memcpy(&udpPacketBuffer[2*global::USHORT_INT_SIZE], &curTime, global::ULONG_LONG_SIZE);
if(peersock == -1)
{
logWrite(EXCEPTION, "udpWriteMessage called in KernelTcp before connect()ing the socket");
peersock = socket(AF_INET, SOCK_DGRAM, 0);
if(peersock < 0)
{
logWrite(ERROR, "Could not create a datagram socket in writeUdpMessage");
return -1;
}
udpLocalAddr.sin_family = AF_INET;
udpLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(peersock, (struct sockaddr *)&udpLocalAddr, sizeof(udpLocalAddr));
}
// result.planet.ip and result.planet.remotePort denote the destination.
// result.planet.ip is in host order
// result.planet.remotePort is in host order
struct sockaddr_in remoteServAddr;
remoteServAddr.sin_family = AF_INET;
remoteServAddr.sin_addr.s_addr = htonl(result.planet.ip);
remoteServAddr.sin_port = htons(result.planet.remotePort);
int flags = 0;
int bytesWritten = sendto(peersock, udpPacketBuffer, size, flags,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
// put the localport in host order in result.planet.localPort
// set result.bufferFull to false (UDP 'buffers' are never full)
// set result.isConnected to true (UDP 'connections' are always connected)
result.planet.localPort = ntohs(udpLocalAddr.sin_port);
result.bufferFull = false;
result.isConnected = true;
if(bytesWritten < 0)
{
logWrite(EXCEPTION, "Error writing to UDP socket in KernelTcp, errno = %d",errno);
return -1;
}
udpCurSeqNum++;
return bytesWritten;
}
bool KernelTcp::isConnected(void)
......
......@@ -17,6 +17,7 @@ enum ConnectionState
CONNECTED
};
class KernelTcp : public ConnectionModel
{
public:
......@@ -34,6 +35,11 @@ private:
int writeUdpMessage(int size, WriteResult & result);
private:
ConnectionState state;
// Udp - CHANGES - Begin
unsigned short udpCurSeqNum;
char udpPacketBuffer[1530];
struct sockaddr_in udpLocalAddr;
// Udp - CHANGES - End
int peersock;
int sendBufferSize;
int receiveBufferSize;
......
......@@ -4,70 +4,122 @@
# All rights reserved.
#
#CC=g++ -g
CC=g++
OBJECTS=CircularTraffic.o \
Command.o \
Connection.o \
Decayer.o \
DelaySensor.o \
DirectInput.o \
EwmaThroughputSensor.o \
KernelTcp.o \
MaxDelaySensor.o \
MinDelaySensor.o \
PacketSensor.o \
Sensor.o \
SensorList.o \
StateSensor.o \
ThroughputSensor.o \
Time.o \
TrivialCommandOutput.o \
log.o \
main.o \
saveload.o \
lib.o \
TSThroughputSensor.o \
LeastSquaresThroughput.o \
UdpPacketSensor.o \
UdpMinDelaySensor.o \
UdpMaxDelaySensor.o \
UdpThroughputSensor.o
all: magent
magent: CircularTraffic.o Command.o Connection.o Decayer.o DelaySensor.o DirectInput.o EwmaThroughputSensor.o KernelTcp.o MaxDelaySensor.o MinDelaySensor.o PacketSensor.o Sensor.o SensorList.o StateSensor.o ThroughputSensor.o Time.o TrivialCommandOutput.o log.o main.o saveload.o
g++ -I. -g -Wall CircularTraffic.o Command.o Connection.o Decayer.o DelaySensor.o DirectInput.o EwmaThroughputSensor.o KernelTcp.o MaxDelaySensor.o MinDelaySensor.o PacketSensor.o Sensor.o SensorList.o StateSensor.o ThroughputSensor.o Time.o TrivialCommandOutput.o log.o main.o saveload.o -lm -lpcap -o magent
magent: ${OBJECTS}
${CC} -I. -Wall $+ -lm -lpcap -o magent
UdpThroughputSensor.o: UdpThroughputSensor.cc UdpThroughputSensor.h UdpPacketSensor.h Sensor.h lib.h
${CC} -I. -Wall -c $<
UdpMaxDelaySensor.o: UdpMaxDelaySensor.cc UdpMaxDelaySensor.h UdpPacketSensor.h UdpMinDelaySensor.h Sensor.h lib.h
${CC} -I. -Wall -c $<
UdpMinDelaySensor.o: UdpMinDelaySensor.cc UdpMinDelaySensor.h UdpPacketSensor.h lib.h
${CC} -I. -Wall -c $<
UdpPacketSensor.o: UdpPacketSensor.cc UdpPacketSensor.h lib.h
${CC} -I. -Wall -c $<
TSThroughputSensor.o: TSThroughputSensor.cc TSThroughputSensor.h lib.h Sensor.h ThroughputSensor.h PacketSensor.h StateSensor.h
${CC} -I. -Wall -c TSThroughputSensor.cc
LeastSquaresThroughput.o: LeastSquaresThroughput.cc LeastSquaresThroughput.h Sensor.h TSThroughputSensor.h DelaySensor.h lib.h CommandOutput.h
${CC} -I. -Wall -c LeastSquaresThroughput.cc
CircularTraffic.o: CircularTraffic.cc lib.h log.h TrafficModel.h CircularTraffic.h Command.h ConnectionModel.h
g++ -I. -g -Wall -c CircularTraffic.cc
${CC} -I. -Wall -c CircularTraffic.cc
Command.o: Command.cc lib.h Command.h Sensor.h Connection.h ConnectionModel.h TrafficModel.h CircularTraffic.h
g++ -I. -g -Wall -c Command.cc
${CC} -I. -Wall -c Command.cc
Connection.o: Connection.cc lib.h log.h Connection.h Time.h ConnectionModel.h TrafficModel.h Sensor.h
g++ -I. -g -Wall -c Connection.cc
${CC} -I. -Wall -c Connection.cc
Decayer.o: Decayer.cc lib.h Decayer.h
g++ -I. -g -Wall -c Decayer.cc
${CC} -I. -Wall -c Decayer.cc
DelaySensor.o: DelaySensor.cc lib.h Sensor.h DelaySensor.h PacketSensor.h Time.h StateSensor.h
g++ -I. -g -Wall -c DelaySensor.cc
${CC} -I. -Wall -c DelaySensor.cc
DirectInput.o: DirectInput.cc lib.h log.h CommandInput.h saveload.h DirectInput.h
g++ -I. -g -Wall -c DirectInput.cc
${CC} -I. -Wall -c DirectInput.cc
EwmaThroughputSensor.o: EwmaThroughputSensor.cc lib.h Sensor.h EwmaThroughputSensor.h ThroughputSensor.h CommandOutput.h
g++ -I. -g -Wall -c EwmaThroughputSensor.cc
${CC} -I. -Wall -c EwmaThroughputSensor.cc
KernelTcp.o: KernelTcp.cc lib.h log.h KernelTcp.h Command.h
g++ -I. -g -Wall -c KernelTcp.cc
${CC} -I. -Wall -c KernelTcp.cc
MaxDelaySensor.o: MaxDelaySensor.cc lib.h Sensor.h Decayer.h MaxDelaySensor.h DelaySensor.h log.h saveload.h CommandOutput.h StateSensor.h
g++ -I. -g -Wall -c MaxDelaySensor.cc
${CC} -I. -Wall -c MaxDelaySensor.cc
MinDelaySensor.o: MinDelaySensor.cc lib.h Sensor.h Decayer.h MinDelaySensor.h DelaySensor.h log.h saveload.h CommandOutput.h
g++ -I. -g -Wall -c MinDelaySensor.cc
${CC} -I. -Wall -c MinDelaySensor.cc
PacketSensor.o: PacketSensor.cc lib.h Sensor.h PacketSensor.h StateSensor.h
g++ -I. -g -Wall -c PacketSensor.cc
${CC} -I. -Wall -c PacketSensor.cc
Sensor.o: Sensor.cc lib.h Sensor.h
g++ -I. -g -Wall -c Sensor.cc
${CC} -I. -Wall -c Sensor.cc
SensorList.o: SensorList.cc lib.h log.h SensorList.h Sensor.h Command.h PacketSensor.h DelaySensor.h MinDelaySensor.h MaxDelaySensor.h ThroughputSensor.h StateSensor.h EwmaThroughputSensor.h
g++ -I. -g -Wall -c SensorList.cc
${CC} -I. -Wall -c SensorList.cc
StateSensor.o: StateSensor.cc lib.h Sensor.h StateSensor.h
g++ -I. -g -Wall -c StateSensor.cc
${CC} -I. -Wall -c StateSensor.cc
ThroughputSensor.o: ThroughputSensor.cc lib.h Sensor.h ThroughputSensor.h PacketSensor.h StateSensor.h
g++ -I. -g -Wall -c ThroughputSensor.cc
${CC} -I. -Wall -c ThroughputSensor.cc
Time.o: Time.cc lib.h Time.h
g++ -I. -g -Wall -c Time.cc
${CC} -I. -Wall -c Time.cc
TrivialCommandOutput.o: TrivialCommandOutput.cc lib.h log.h saveload.h CommandOutput.h TrivialCommandOutput.h CommandInput.h
g++ -I. -g -Wall -c TrivialCommandOutput.cc
${CC} -I. -Wall -c TrivialCommandOutput.cc
log.o: log.cc lib.h log.h
g++ -I. -g -Wall -c log.cc
${CC} -I. -Wall -c log.cc
main.o: main.cc lib.h log.h CommandInput.h CommandOutput.h Command.h Time.h Connection.h Sensor.h TrafficModel.h KernelTcp.h saveload.h DirectInput.h TrivialCommandOutput.h
g++ -I. -g -Wall -c main.cc
${CC} -I. -Wall -c main.cc
saveload.o: saveload.cc lib.h log.h saveload.h Command.h
g++ -I. -g -Wall -c saveload.cc
${CC} -I. -Wall -c saveload.cc
lib.o: lib.cc lib.h
${CC} -I. -Wall -c lib.cc
clean:
rm *.o magent
......@@ -28,6 +28,14 @@ long long Time::toMilliseconds(void) const
return result;
}
// Udp - CHANGES - Begin
unsigned long long Time::toMicroseconds(void) const
{
unsigned long long result = data.tv_sec * 1000 * 1000 + data.tv_usec;
return result;
}
// Udp - CHANGES - End
double Time::toDouble(void) const
{
double result = data.tv_sec + data.tv_usec / 1000000.0;
......
......@@ -15,6 +15,9 @@ public:
Time();
Time(struct timeval const & newData);
long long toMilliseconds(void) const;
// Udp - CHANGES - Begin
unsigned long long toMicroseconds(void) const;
// Udp - CHANGES - End
double toDouble(void) const;
struct timeval * getTimeval(void);
struct timeval const * getTimeval(void) const;
......
#include "UdpMaxDelaySensor.h"
UdpMaxDelaySensor::UdpMaxDelaySensor(UdpPacketSensor *udpPacketSensorVal, UdpMinDelaySensor *minDelaySensorVal)
: maxDelay(0),
packetHistory(udpPacketSensorVal),
minDelaySensor(minDelaySensorVal)
{
}
UdpMaxDelaySensor::~UdpMaxDelaySensor()
{
}
void UdpMaxDelaySensor::localSend(PacketInfo *packet)
{
}
void UdpMaxDelaySensor::localAck(PacketInfo *packet)
{
// This is a re-ordered ACK or a corrupted packet - don't do anything
// with it - just return.
if( packetHistory->isAckValid() == false )
return;
int overheadLen = 14 + 4 + 8 + packet->ip->ip_hl*4;
unsigned short int seqNum = *(unsigned short int *)(packet->payload + 1);
unsigned short int echoedPacketSize = *(unsigned short int *)(packet->payload + 1 + global::USHORT_INT_SIZE);
unsigned long long echoedTimestamp = *(unsigned long long *)(packet->payload + 1 + 2*global::USHORT_INT_SIZE + global::ULONG_LONG_SIZE);
unsigned long long oneWayQueueDelay;
bool eventFlag = false;
vector<UdpPacketInfo>::iterator vecIterator;
vecIterator = find_if(packetHistory->ackedPackets.begin(), packetHistory->ackedPackets.end(), bind2nd(equalSeqNum(), seqNum));
// Find the one way RTT for this packet.
unsigned long long timeStamp = packet->packetTime.toMicroseconds();
// We lost this packet send time due to loss in libpcap, use the
// time echoed in the ACK packet.
if(packetHistory->isAckFake() == true)
oneWayQueueDelay = (timeStamp - echoedTimestamp)/2;
else
oneWayQueueDelay = (timeStamp - (*vecIterator).timeStamp)/2;
// Scale the value of one way RTT, so that it is correct for a transmission
// size of 1518 bytes.
// We lost this packet size details due to loss in libpcap, use the
// size echoed in the ACK packet - this does not included the header
// overhead for the packet - we assume that the packet on the reverse path
// has the same overhead length as the original packet.
if(packetHistory->isAckFake() == true)
oneWayQueueDelay = ( oneWayQueueDelay )*1518 / (overheadLen + echoedPacketSize);
else
oneWayQueueDelay = ( oneWayQueueDelay )*1518 / ((*vecIterator).packetSize);
// Find the queuing delay for this packet, by subtracting the
// one way minimum delay from the above value.
oneWayQueueDelay = oneWayQueueDelay - minDelaySensor->getMinDelay();
// Set this as the new maximum one way queuing delay.
if(oneWayQueueDelay > maxDelay)
{
eventFlag = true;
maxDelay = oneWayQueueDelay;
}
// Send an event message to the monitor to change the value of maximum one way delay.
if(eventFlag == true)
{
// Report the maximum delay
logWrite(SENSOR,"VALUE::New Max Delay = %llu",maxDelay);
}
logWrite(SENSOR,"MAXD:TIME=%llu,MAXD=%llu",timeStamp,maxDelay);
logWrite(SENSOR,"ACTUAL_MAXD:TIME=%llu,ACTUAL_MAXD=%llu",timeStamp,oneWayQueueDelay);
}
#ifndef UDP_MAX_DELAY_SENSOR_PELAB_H
#define UDP_MAX_DELAY_SENSOR_PELAB_H
#include "lib.h"
#include "UdpPacketSensor.h"
#include "UdpMinDelaySensor.h"
#include "Sensor.h"
class Sensor;
class UdpPacketSensor;
class UdpMinDelaySensor;
class UdpMaxDelaySensor:public Sensor{
public:
explicit UdpMaxDelaySensor(UdpPacketSensor *udpPacketSensorVal, UdpMinDelaySensor *minDelaySensorVal);
~UdpMaxDelaySensor();
void localSend(PacketInfo *packet);
void localAck(PacketInfo *packet);
private:
unsigned long long maxDelay;
UdpPacketSensor *packetHistory;
UdpMinDelaySensor *minDelaySensor;
};
#endif
#include "UdpMinDelaySensor.h"
UdpMinDelaySensor::UdpMinDelaySensor(UdpPacketSensor *udpPacketSensorVal)
: minDelay(ULONG_LONG_MAX),
packetHistory(udpPacketSensorVal)
{
}
UdpMinDelaySensor::~UdpMinDelaySensor()
{
}
unsigned long long UdpMinDelaySensor::getMinDelay()
{
return minDelay;
}
void UdpMinDelaySensor::localSend(PacketInfo *packet)
{
// Do nothing.
sendValid = true;
ackValid = false;
}
void UdpMinDelaySensor::localAck(PacketInfo *packet)
{
if( ( ntohs(packet->udp->len) - 8 ) < global::udpMinAckPacketSize )
{
logWrite(ERROR, "UDP packet data sent to UdpMinDelaySensor::localAck was less than the "
" required minimum %d bytes",global::udpMinAckPacketSize);
ackValid = false;
sendValid = false;
return;
}
// This is a re-ordered ACK or an incorrect packet - don't do anything
// with it - just return.
if( packetHistory->isAckValid() == false )
{
ackValid = false;
sendValid = false;
return;
}
ackValid = true;
sendValid = false;
int overheadLen = 14 + 4 + 8 + packet->ip->ip_hl*4;
unsigned short int seqNum = *(unsigned short int *)(packet->payload + 1);
unsigned short int echoedPacketSize = *(unsigned short int *)(packet->payload + 1 + global::USHORT_INT_SIZE);
unsigned long long echoedTimestamp = *(unsigned long long *)(packet->payload + 1 + 2*global::USHORT_INT_SIZE + global::ULONG_LONG_SIZE);
unsigned long long oneWayDelay;
bool eventFlag = false;
vector<UdpPacketInfo >::iterator vecIterator;
vecIterator = find_if(packetHistory->ackedPackets.begin(), packetHistory->ackedPackets.end(), bind2nd(equalSeqNum(), seqNum));
// Calculate the one way delay as half of RTT.
unsigned long long timeStamp = packet->packetTime.toMicroseconds();
// We lost this packet send time due to loss in libpcap, use the
// time echoed in the ACK packet.
if(packetHistory->isAckFake() == true)
oneWayDelay = (timeStamp - echoedTimestamp)/2;
else
oneWayDelay = (timeStamp - (*vecIterator).timeStamp)/2;
// Calculate the delay for the maximum sized packet.
// We lost this packet size details due to loss in libpcap, use the
// size echoed in the ACK packet - this does not included the header
// overhead for the packet - we assume that the packet on the reverse path
// has the same overhead length as the original packet.
if(packetHistory->isAckFake() == true)
oneWayDelay = ( oneWayDelay ) * 1518 / (overheadLen + echoedPacketSize);
else
oneWayDelay = ( oneWayDelay ) * 1518 / ( (*vecIterator).packetSize);
// Set this as the new minimum one way delay.
if(oneWayDelay < minDelay)
{
eventFlag = true;
minDelay = oneWayDelay;
}
// 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.
// Send an event message to the monitor to change the value of minimum one way delay.
if(eventFlag == true)
{
logWrite(SENSOR,"VALUE::New Min delay = %llu",minDelay);
}
logWrite(SENSOR,"MIND:TIME=%llu,MIND=%llu",timeStamp,minDelay);
}
#ifndef UDP_MIN_DELAY_SENSOR_PELAB_H
#define UDP_MIN_DELAY_SENSOR_PELAB_H
#include "lib.h"
#include "Sensor.h"
#include "UdpPacketSensor.h"
class Sensor;
class UdpPacketSensor;
class UdpMinDelaySensor:public Sensor{
public:
explicit UdpMinDelaySensor(UdpPacketSensor *udpPacketSensorVal);
~UdpMinDelaySensor();
unsigned long long getMinDelay();
void localSend(PacketInfo *packet);
void localAck(PacketInfo *packet);
private:
unsigned long long minDelay;
UdpPacketSensor *packetHistory;
};
#endif
#include "UdpPacketSensor.h"
UdpPacketSensor::UdpPacketSensor()
:lastSeenSeqNum(-1),
packetLoss(0),
totalPacketLoss(0),
libpcapSendLoss(0),
ackFake(false)
{
}
UdpPacketSensor::~UdpPacketSensor()
{
// Empty the list used to store the packets.
sentPacketList.clear();
}
int UdpPacketSensor::getPacketLoss()
{
return packetLoss;
}
bool UdpPacketSensor::isAckFake()
{
return ackFake;
}
void UdpPacketSensor::localSend(PacketInfo *packet)
{
int overheadLen = 14 + 4 + 8 + packet->ip->ip_hl*4;
if( ( ntohs(packet->udp->len ) - 8) < global::udpMinSendPacketSize )
{
logWrite(ERROR, "UDP packet data sent to UdpPacketSensor::localSend"
" was less than the "
" required minimum %d bytes", global::udpMinSendPacketSize);
sendValid = false;
ackValid = false;
return;
}
sendValid = true;
ackValid = false;
unsigned short int seqNum = *(unsigned short int *)(packet->payload);
unsigned short int packetSize = *(unsigned short int *)(packet->payload + global::USHORT_INT_SIZE) + overheadLen;
UdpPacketInfo tmpPacketInfo;
if(lastSeenSeqNum != -1)
{
// We missed some packets because of loss in libpcap buffer.
// Add fake packets to the sent list, their sizes and time stamps
// are unknown - but they can be gathered from the ACK packets.
if(seqNum > (lastSeenSeqNum + 1))
{
for(int i = 1;i < seqNum - lastSeenSeqNum ; i++)
{
tmpPacketInfo.seqNum = lastSeenSeqNum + i;
tmpPacketInfo.isFake = true;
sentPacketList.push_back(tmpPacketInfo);
}
libpcapSendLoss += (seqNum - lastSeenSeqNum - 1);
}
}
lastSeenSeqNum = seqNum;
tmpPacketInfo.seqNum = seqNum;
tmpPacketInfo.packetSize = packetSize;
tmpPacketInfo.timeStamp = packet->packetTime.toMicroseconds();
tmpPacketInfo.isFake = false;
sentPacketList.push_back(tmpPacketInfo);
}
void UdpPacketSensor::localAck(PacketInfo *packet)
{
if( ( ntohs(packet->udp->len ) - 8) < global::udpMinAckPacketSize )
{
logWrite(ERROR, "UDP packet data sent to UdpPacketSensor::localAck"
" was less than the "
" minimum %d bytes ",global::udpMinAckPacketSize);
ackValid = false;
return;
}
unsigned short int seqNum = *(unsigned short int *)(packet->payload + 1);
// Find the entry for the packet this ACK is acknowledging, and
// remove it from the sent(&unacked) packet list.
list<UdpPacketInfo >::iterator listIterator;
listIterator = find_if(sentPacketList.begin(), sentPacketList.end(), bind2nd(equalSeqNum(), seqNum));
if(listIterator == sentPacketList.end())
{
logWrite(EXCEPTION, "Unknown UDP seq number %d is being ACKed. "
"We might have received "
" a reordered ACK, which has already been ACKed using redundant ACKs .\n", seqNum);
ackValid = false;
}
else
ackValid = true;
// We received an ACK correctly(without reordering), but we dont have any record of ever
// sending the original packet(Actually, we have a fake packet inserted into our send list)
// -- this indicates libpcap loss.
if( (*listIterator).isFake == true)
ackFake = true;
else
ackFake = false;
// Remove the old state information.
ackedPackets.clear();
packetLoss = 0;
int i;
unsigned char numRedunAcksChar = 0;
int numRedunAcks = 0;
// Read how many redundant ACKs are being sent in this packet.
memcpy(&numRedunAcksChar, &packet->payload[0], global::UCHAR_SIZE);
numRedunAcks = static_cast<int>(numRedunAcksChar);
// Store an iterator to the current seqNum being acknowledge, and delete it at the end.
list<UdpPacketInfo >::iterator curPacketIterator = listIterator;
// Look at the redundant ACKs first.
UdpPacketInfo tmpPacketInfo;
if(numRedunAcks > 0)
{
unsigned short int redunSeqNum;
for(i = 0; i < numRedunAcks; i++)
{
redunSeqNum = *(unsigned short int *)(packet->payload + global::udpMinAckPacketSize + i*global::udpRedunAckSize);
listIterator = sentPacketList.end();
// 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(), curPacketIterator, bind2nd(equalSeqNum(), redunSeqNum));
// An unacked packet exists with this sequence number, delete it
// from the list and consider it acked.
if(listIterator != curPacketIterator && listIterator != sentPacketList.end())
{
tmpPacketInfo.seqNum = (*listIterator).seqNum;
tmpPacketInfo.packetSize = (*listIterator).packetSize;
tmpPacketInfo.timeStamp = (*listIterator).timeStamp;
tmpPacketInfo.isFake = (*listIterator).isFake;
ackedPackets.push_back(tmpPacketInfo);
sentPacketList.erase(listIterator);
}
}
}
tmpPacketInfo.seqNum = (*curPacketIterator).seqNum;
tmpPacketInfo.packetSize = (*curPacketIterator).packetSize;
tmpPacketInfo.timeStamp = (*curPacketIterator).timeStamp;
tmpPacketInfo.isFake = (*curPacketIterator).isFake;
ackedPackets.push_back(tmpPacketInfo);
// Check for packet loss - if we have any unacked packets with sequence
// numbers less than the received ACK seq number, then the packets/or their ACKS
// were lost - treat this as congestion on the forward path.
// Find out how many packets were lost.
listIterator = find_if(sentPacketList.begin(), curPacketIterator, bind2nd(lessSeqNum(), seqNum));
if( (listIterator != sentPacketList.end()) && (listIterator != curPacketIterator ))
{
logWrite(SENSOR, "STAT::Packet being ACKed = %d",seqNum);
do{
logWrite(SENSOR, "STAT::Lost packet seqnum = %d",(*listIterator).seqNum);
sentPacketList.erase(listIterator);