Implements the UDP protocol: encapsulates/decapsulates user data into/from UDP. More...
#include <SimpleUDP.h>
Classes | |
struct | SockDesc |
defines a socket More... | |
Public Types | |
enum | delayFaultTypeNum { delayFaultUndefined, delayFaultLiveAll, delayFaultLivePlanetlab, delayFaultSimulation } |
typedef std::list< SockDesc * > | SockDescList |
list of socket pointers | |
typedef std::map< int, SockDesc * > | SocketsByIdMap |
list of socket ordered by sockId | |
typedef std::map< int, SockDescList > | SocketsByPortMap |
list of sockets ordered by localPort | |
Public Member Functions | |
void | setNodeEntry (SimpleNodeEntry *entry) |
set or change the nodeEntry of this module | |
SimpleUDP () | |
virtual | ~SimpleUDP () |
destructor | |
Static Public Attributes | |
static std::string | delayFaultTypeString |
static std::map< std::string, delayFaultTypeNum > | delayFaultTypeMap |
Protected Member Functions | |
void | updateDisplayString () |
utility: show current statistics above the icon | |
void | bind (int gateIndex, UDPControlInfo *ctrl) |
bind socket | |
void | connect (int sockId, IPvXAddress addr, int port) |
connect socket | |
void | unbind (int sockId) |
unbind socket | |
short | getEphemeralPort () |
ephemeral port. | |
bool | matchesSocket (SockDesc *sd, SimpleUDPPacket *udp, IPControlInfo *ctrl) |
decides if a received packet (IPv4) belongs to the specified socket | |
bool | matchesSocket (SockDesc *sd, SimpleUDPPacket *udp, IPv6ControlInfo *ctrl) |
decides if a received packet (IPv6) belongs to the specified socket | |
bool | matchesSocket (SockDesc *sd, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, short remotePort) |
decides if a socket matches the specified parameters | |
void | sendUp (cMessage *payload, SimpleUDPPacket *udpHeader, IPControlInfo *ctrl, SockDesc *sd) |
sends payload up to the application | |
void | sendUp (cMessage *payload, SimpleUDPPacket *udpHeader, IPv6ControlInfo *ctrl, SockDesc *sd) |
sends payload up to the application | |
void | processUndeliverablePacket (SimpleUDPPacket *udpPacket, cPolymorphic *ctrl) |
handles received packet which destination port is not bound to any socket | |
void | sendUpErrorNotification (SockDesc *sd, int msgkind, const IPvXAddress &localAddr, const IPvXAddress &remoteAddr, short remotePort) |
sends an error up to the application | |
virtual void | processICMPError (cMessage *icmpErrorMsg) |
process an ICMP error packet | |
virtual void | processUDPPacket (SimpleUDPPacket *udpPacket) |
process UDP packets coming from IP | |
virtual void | processMsgFromApp (cPacket *appData) |
process packets from application | |
virtual void | processCommandFromApp (cMessage *msg) |
process commands from application | |
virtual void | initialize (int stage) |
initialise the SimpleUDP module | |
virtual int | numInitStages () const |
returns the number of init stages | |
virtual void | handleMessage (cMessage *msg) |
process received messages | |
void | finish () |
Protected Attributes | |
SocketsByIdMap | socketsByIdMap |
list of socket ordered by sockId | |
SocketsByPortMap | socketsByPortMap |
list of sockets ordered by localPort | |
short | lastEphemeralPort |
last used port (all ports above should be free) | |
ICMP * | icmp |
pointer to a received icmp (IPv4) message | |
ICMPv6 * | icmpv6 |
pointer to a received icmp (IPv6) message | |
int | numSent |
number of packets sent to the network | |
int | numPassedUp |
number of packet passed up to applications | |
int | numDroppedWrongPort |
number of dropped packets due to wrong destination port | |
int | numDroppedBadChecksum |
number of dropped packets due to bad checksum | |
int | numQueueLost |
number of lost packets due to queue full | |
int | numPartitionLost |
number of lost packets due to network partitions | |
int | numDestUnavailableLost |
number of lost packets due to unavailable destination | |
simtime_t | delay |
simulated delay between sending and receiving udp module | |
simtime_t | constantDelay |
constant delay between two peers | |
bool | useCoordinateBasedDelay |
delay should be calculated from euklidean distance between two peers | |
double | jitter |
amount of jitter in % of total delay | |
bool | faultyDelay |
GlobalNodeList * | globalNodeList |
violate the triangle inequality? | |
GlobalStatistics * | globalStatistics |
pointer to GlobalStatistics | |
SimpleNodeEntry * | nodeEntry |
nodeEntry of the overlay node this module belongs to |
Implements the UDP protocol: encapsulates/decapsulates user data into/from UDP.
More info in the NED file.
Definition at line 63 of file SimpleUDP.h.
typedef std::list<SockDesc *> SimpleUDP::SockDescList |
list of socket pointers
Definition at line 84 of file SimpleUDP.h.
typedef std::map<int,SockDesc *> SimpleUDP::SocketsByIdMap |
list of socket ordered by sockId
Definition at line 85 of file SimpleUDP.h.
typedef std::map<int,SockDescList> SimpleUDP::SocketsByPortMap |
list of sockets ordered by localPort
Definition at line 86 of file SimpleUDP.h.
Definition at line 90 of file SimpleUDP.h.
00090 { 00091 delayFaultUndefined, 00092 delayFaultLiveAll, 00093 delayFaultLivePlanetlab, 00094 delayFaultSimulation 00095 };
SimpleUDP::SimpleUDP | ( | ) |
Definition at line 92 of file SimpleUDP.cc.
00093 { 00094 globalStatistics = NULL; 00095 }
SimpleUDP::~SimpleUDP | ( | ) | [virtual] |
destructor
Definition at line 97 of file SimpleUDP.cc.
00098 { 00099 for (SocketsByIdMap::iterator i=socketsByIdMap.begin(); 00100 i!=socketsByIdMap.end(); ++i) 00101 delete i->second; 00102 }
void SimpleUDP::bind | ( | int | gateIndex, | |
UDPControlInfo * | ctrl | |||
) | [protected] |
bind socket
gateIndex | application gate connected to the socket | |
ctrl | control information for communication |
Definition at line 169 of file SimpleUDP.cc.
Referenced by processCommandFromApp().
00170 { 00171 // XXX checks could be added, of when the bind should be allowed to proceed 00172 00173 if (ctrl->getSrcPort() <= 0 || ctrl->getSrcPort() > 65535) 00174 opp_error("bind: invalid src port number %d", ctrl->getSrcPort()); 00175 00176 // create and fill in SockDesc 00177 SockDesc *sd = new SockDesc(); 00178 sd->sockId = ctrl->getSockId(); 00179 sd->userId = ctrl->getUserId(); 00180 sd->appGateIndex = gateIndex; 00181 sd->localAddr = ctrl->getSrcAddr(); 00182 sd->remoteAddr = ctrl->getDestAddr(); 00183 sd->localPort = ctrl->getSrcPort(); 00184 sd->remotePort = ctrl->getDestPort(); 00185 sd->interfaceId = ctrl->getInterfaceId(); 00186 00187 if (sd->sockId==-1) 00188 error("sockId in BIND message not filled in"); 00189 if (sd->localPort==0) 00190 sd->localPort = getEphemeralPort(); 00191 00192 sd->onlyLocalPortIsSet = sd->localAddr.isUnspecified() && 00193 sd->remoteAddr.isUnspecified() && 00194 sd->remotePort==0 && 00195 sd->interfaceId==-1; 00196 00197 cModule *node = getParentModule(); 00198 IPvXAddress ip = IPAddressResolver().addressOf(node); 00199 EV << "[SimpleUDP::bind() @ " << ip << "]\n" 00200 << " Binding socket: " << *sd 00201 << endl; 00202 00203 // add to socketsByIdMap 00204 ASSERT(socketsByIdMap.find(sd->sockId)==socketsByIdMap.end()); 00205 socketsByIdMap[sd->sockId] = sd; 00206 00207 // add to socketsByPortMap 00208 // create if doesn't exist 00209 SockDescList& list = socketsByPortMap[sd->localPort]; 00210 list.push_back(sd); 00211 }
void SimpleUDP::connect | ( | int | sockId, | |
IPvXAddress | addr, | |||
int | port | |||
) | [protected] |
connect socket
sockId | id of the socket to connect | |
addr | IPvXAddress of the remote socket | |
port | port of the remote socket |
Definition at line 213 of file SimpleUDP.cc.
Referenced by processCommandFromApp().
00214 { 00215 SocketsByIdMap::iterator it = socketsByIdMap.find(sockId); 00216 if (it==socketsByIdMap.end()) 00217 error("socket id=%d doesn't exist (already closed?)", sockId); 00218 if (addr.isUnspecified()) 00219 opp_error("connect: unspecified remote address"); 00220 if (port<=0 || port>65535) 00221 opp_error("connect: invalid remote port number %d", port); 00222 00223 SockDesc *sd = it->second; 00224 sd->remoteAddr = addr; 00225 sd->remotePort = port; 00226 00227 sd->onlyLocalPortIsSet = false; 00228 00229 EV << "[SimpleUDP::connect() @ " << sd->localAddr << "]\n" 00230 << " Connecting socket: " << *sd 00231 << endl; 00232 }
void SimpleUDP::finish | ( | ) | [protected] |
Definition at line 155 of file SimpleUDP.cc.
00156 { 00157 globalStatistics->addStdDev("SimpleUDP: Packets sent", 00158 numSent); 00159 globalStatistics->addStdDev("SimpleUDP: Packets dropped with bad checksum", 00160 numDroppedBadChecksum); 00161 globalStatistics->addStdDev("SimpleUDP: Packets dropped due to queue overflows", 00162 numQueueLost); 00163 globalStatistics->addStdDev("SimpleUDP: Packets dropped due to network partitions", 00164 numPartitionLost); 00165 globalStatistics->addStdDev("SimpleUDP: Packets dropped due to unavailable destination", 00166 numDestUnavailableLost); 00167 }
short SimpleUDP::getEphemeralPort | ( | ) | [protected] |
ephemeral port.
Definition at line 259 of file SimpleUDP.cc.
Referenced by bind().
00260 { 00261 // start at the last allocated port number + 1, and search for an unused one 00262 short searchUntil = lastEphemeralPort++; 00263 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap 00264 lastEphemeralPort = EPHEMERAL_PORTRANGE_START; 00265 00266 while (socketsByPortMap.find(lastEphemeralPort)!=socketsByPortMap.end()) { 00267 if (lastEphemeralPort == searchUntil) // got back to starting point? 00268 error("Ephemeral port range %d..%d exhausted, all ports occupied", EPHEMERAL_PORTRANGE_START, EPHEMERAL_PORTRANGE_END); 00269 lastEphemeralPort++; 00270 if (lastEphemeralPort == EPHEMERAL_PORTRANGE_END) // wrap 00271 lastEphemeralPort = EPHEMERAL_PORTRANGE_START; 00272 } 00273 00274 // found a free one, return it 00275 return lastEphemeralPort; 00276 }
void SimpleUDP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
process received messages
msg | the received message |
Definition at line 278 of file SimpleUDP.cc.
00279 { 00280 // received from the network layer 00281 if (msg->arrivedOn("network_in")) { 00282 if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg)) 00283 processICMPError(msg); 00284 else 00285 processUDPPacket(check_and_cast<SimpleUDPPacket *>(msg)); 00286 } else // received from application layer 00287 { 00288 if (msg->getKind()==UDP_C_DATA) 00289 processMsgFromApp(check_and_cast<cPacket*>(msg)); 00290 else 00291 processCommandFromApp(msg); 00292 } 00293 00294 if (ev.isGUI()) 00295 updateDisplayString(); 00296 }
void SimpleUDP::initialize | ( | int | stage | ) | [protected, virtual] |
initialise the SimpleUDP module
stage | stage of initialisation phase |
Definition at line 104 of file SimpleUDP.cc.
00105 { 00106 if(stage == MIN_STAGE_UNDERLAY) { 00107 WATCH_PTRMAP(socketsByIdMap); 00108 WATCH_MAP(socketsByPortMap); 00109 00110 lastEphemeralPort = EPHEMERAL_PORTRANGE_START; 00111 icmp = NULL; 00112 icmpv6 = NULL; 00113 00114 numSent = 0; 00115 numPassedUp = 0; 00116 numDroppedWrongPort = 0; 00117 numDroppedBadChecksum = 0; 00118 numQueueLost = 0; 00119 numPartitionLost = 0; 00120 numDestUnavailableLost = 0; 00121 WATCH(numSent); 00122 WATCH(numPassedUp); 00123 WATCH(numDroppedWrongPort); 00124 WATCH(numDroppedBadChecksum); 00125 WATCH(numQueueLost); 00126 WATCH(numPartitionLost); 00127 WATCH(numDestUnavailableLost); 00128 00129 globalNodeList = GlobalNodeListAccess().get(); 00130 globalStatistics = GlobalStatisticsAccess().get(); 00131 constantDelay = par("constantDelay"); 00132 useCoordinateBasedDelay = par("useCoordinateBasedDelay"); 00133 00134 delayFaultTypeString = par("delayFaultType").stdstringValue(); 00135 delayFaultTypeMap["live_all"] = delayFaultLiveAll; 00136 delayFaultTypeMap["live_planetlab"] = delayFaultLivePlanetlab; 00137 delayFaultTypeMap["simulation"] = delayFaultSimulation; 00138 00139 switch (delayFaultTypeMap[delayFaultTypeString]) { 00140 case SimpleUDP::delayFaultLiveAll: 00141 case SimpleUDP::delayFaultLivePlanetlab: 00142 case SimpleUDP::delayFaultSimulation: 00143 faultyDelay = true; 00144 break; 00145 default: 00146 faultyDelay = false; 00147 } 00148 00149 jitter = par("jitter"); 00150 nodeEntry = NULL; 00151 WATCH_PTR(nodeEntry); 00152 } 00153 }
bool SimpleUDP::matchesSocket | ( | SockDesc * | sd, | |
const IPvXAddress & | localAddr, | |||
const IPvXAddress & | remoteAddr, | |||
short | remotePort | |||
) | [protected] |
decides if a socket matches the specified parameters
sd | the socket | |
localAddr | the specified localAddr | |
remoteAddr | the specified remoteAddr | |
remotePort | the specified remotePort |
Definition at line 341 of file SimpleUDP.cc.
bool SimpleUDP::matchesSocket | ( | SockDesc * | sd, | |
SimpleUDPPacket * | udp, | |||
IPv6ControlInfo * | ctrl | |||
) | [protected] |
decides if a received packet (IPv6) belongs to the specified socket
sd | the socket | |
udp | the received SimpleUDPPacket | |
ctrl | the IPControlInfo of udp |
Definition at line 327 of file SimpleUDP.cc.
00328 { 00329 // IPv6 version 00330 if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort()) 00331 return false; 00332 if (!sd->localAddr.isUnspecified() && sd->localAddr.get6()!=ipCtrl->getDestAddr()) 00333 return false; 00334 if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get6()!=ipCtrl->getSrcAddr()) 00335 return false; 00336 if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId()) 00337 return false; 00338 return true; 00339 }
bool SimpleUDP::matchesSocket | ( | SockDesc * | sd, | |
SimpleUDPPacket * | udp, | |||
IPControlInfo * | ctrl | |||
) | [protected] |
decides if a received packet (IPv4) belongs to the specified socket
sd | the socket | |
udp | the received SimpleUDPPacket | |
ctrl | the IPControlInfo of udp |
Definition at line 313 of file SimpleUDP.cc.
Referenced by processICMPError(), and processUDPPacket().
00314 { 00315 // IPv4 version 00316 if (sd->remotePort!=0 && sd->remotePort!=udp->getSourcePort()) 00317 return false; 00318 if (!sd->localAddr.isUnspecified() && sd->localAddr.get4()!=ipCtrl->getDestAddr()) 00319 return false; 00320 if (!sd->remoteAddr.isUnspecified() && sd->remoteAddr.get4()!=ipCtrl->getSrcAddr()) 00321 return false; 00322 if (sd->interfaceId!=-1 && sd->interfaceId!=ipCtrl->getInterfaceId()) 00323 return false; 00324 return true; 00325 }
virtual int SimpleUDP::numInitStages | ( | void | ) | const [inline, protected, virtual] |
returns the number of init stages
Definition at line 288 of file SimpleUDP.h.
00289 { 00290 return MAX_STAGE_UNDERLAY + 1; 00291 }
void SimpleUDP::processCommandFromApp | ( | cMessage * | msg | ) | [protected, virtual] |
process commands from application
msg | the command message |
Definition at line 739 of file SimpleUDP.cc.
Referenced by handleMessage().
00740 { 00741 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); 00742 switch (msg->getKind()) { 00743 case UDP_C_BIND: 00744 bind(msg->getArrivalGate()->getIndex(), udpCtrl); 00745 break; 00746 case UDP_C_CONNECT: 00747 connect(udpCtrl->getSockId(), udpCtrl->getDestAddr(), udpCtrl->getDestPort()); 00748 break; 00749 case UDP_C_UNBIND: 00750 unbind(udpCtrl->getSockId()); 00751 break; 00752 default: 00753 error("unknown command code (message kind) %d received from app", msg->getKind()); 00754 } 00755 00756 delete udpCtrl; 00757 delete msg; 00758 }
void SimpleUDP::processICMPError | ( | cMessage * | icmpErrorMsg | ) | [protected, virtual] |
process an ICMP error packet
icmpErrorMsg | the received icmp Message |
Definition at line 413 of file SimpleUDP.cc.
Referenced by handleMessage().
00414 { 00415 // extract details from the error message, then try to notify socket that sent bogus packet 00416 int type = 0; 00417 int code = 0; 00418 IPvXAddress localAddr, remoteAddr; 00419 int localPort = 0; 00420 int remotePort = 0; 00421 00422 if (dynamic_cast<ICMPMessage *>(msg)) { 00423 ICMPMessage *icmpMsg = (ICMPMessage *)msg; 00424 type = icmpMsg->getType(); 00425 code = icmpMsg->getCode(); 00426 icmpMsg->setBitLength(icmpMsg->getEncapsulatedPacket()->getBitLength()); // trick because payload in ICMP is conceptually truncated 00427 IPDatagram *datagram = check_and_cast<IPDatagram *>(icmpMsg->decapsulate()); 00428 localAddr = datagram->getSrcAddress(); 00429 remoteAddr = datagram->getDestAddress(); 00430 SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate()); 00431 localPort = packet->getSourcePort(); 00432 remotePort = packet->getDestinationPort(); 00433 delete icmpMsg; 00434 delete datagram; 00435 delete packet; 00436 } else if (dynamic_cast<ICMPv6Message *>(msg)) { 00437 ICMPv6Message *icmpMsg = (ICMPv6Message *)msg; 00438 type = icmpMsg->getType(); 00439 code = -1; // FIXME this is dependent on getType()... 00440 IPv6Datagram *datagram = check_and_cast<IPv6Datagram *>(icmpMsg->decapsulate()); 00441 localAddr = datagram->getSrcAddress(); 00442 remoteAddr = datagram->getDestAddress(); 00443 SimpleUDPPacket *packet = check_and_cast<SimpleUDPPacket *>(datagram->decapsulate()); 00444 localPort = packet->getSourcePort(); 00445 remotePort = packet->getDestinationPort(); 00446 delete icmpMsg; 00447 delete datagram; 00448 delete packet; 00449 } 00450 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00451 << " ICMP error received: type=" << type << " code=" << code 00452 << "\n about packet " << localAddr << ":" << localPort << " --> " 00453 << " " << remoteAddr << ":" << remotePort 00454 << endl; 00455 00456 // identify socket and report error to it 00457 SocketsByPortMap::iterator it = socketsByPortMap.find(localPort); 00458 if (it==socketsByPortMap.end()) { 00459 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00460 << " No socket on that local port, ignoring ICMP error" 00461 << endl; 00462 return; 00463 } 00464 SockDescList& list = it->second; 00465 SockDesc *srcSocket = NULL; 00466 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00467 SockDesc *sd = *it; 00468 if (sd->onlyLocalPortIsSet || matchesSocket(sd, localAddr, remoteAddr, remotePort)) { 00469 srcSocket = sd; // FIXME what to do if there's more than one matching socket ??? 00470 } 00471 } 00472 if (!srcSocket) { 00473 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00474 << " No matching socket, ignoring ICMP error" 00475 << endl; 00476 return; 00477 } 00478 00479 // send UDP_I_ERROR to socket 00480 EV << "[SimpleUDP::processICMPError() @ " << localAddr << "]\n" 00481 << " Source socket is sockId=" << srcSocket->sockId << ", notifying" 00482 << endl; 00483 sendUpErrorNotification(srcSocket, UDP_I_ERROR, localAddr, remoteAddr, remotePort); 00484 }
void SimpleUDP::processMsgFromApp | ( | cPacket * | appData | ) | [protected, virtual] |
process packets from application
appData | the data that has to be sent |
Definition at line 590 of file SimpleUDP.cc.
Referenced by handleMessage().
00591 { 00592 cModule *node = getParentModule(); 00593 // IPvXAddress ip = IPAddressResolver().addressOf(node); 00594 // Speedhack SK 00595 00596 IPvXAddress srcAddr, destAddr; 00597 //cGate* destGate; 00598 00599 UDPControlInfo *udpCtrl = check_and_cast<UDPControlInfo *>(appData->removeControlInfo()); 00600 00601 SimpleUDPPacket *udpPacket = new SimpleUDPPacket(appData->getName()); 00602 00603 // 00604 udpPacket->setByteLength(UDP_HEADER_BYTES + IP_HEADER_BYTES); 00605 udpPacket->encapsulate(appData); 00606 00607 // set source and destination port 00608 udpPacket->setSourcePort(udpCtrl->getSrcPort()); 00609 udpPacket->setDestinationPort(udpCtrl->getDestPort()); 00610 00611 srcAddr = udpCtrl->getSrcAddr(); 00612 destAddr = udpCtrl->getDestAddr(); 00613 if (!udpCtrl->getDestAddr().isIPv6()) { 00614 // send to IPv4 00615 //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00616 //<< " Sending app packet " << appData->getName() << " over IPv4" 00617 //<< endl; 00618 IPControlInfo *ipControlInfo = new IPControlInfo(); 00619 ipControlInfo->setProtocol(IP_PROT_UDP); 00620 ipControlInfo->setSrcAddr(srcAddr.get4()); 00621 ipControlInfo->setDestAddr(destAddr.get4()); 00622 ipControlInfo->setInterfaceId(udpCtrl->getInterfaceId()); 00623 udpPacket->setControlInfo(ipControlInfo); 00624 delete udpCtrl; 00625 } else { 00626 // send to IPv6 00627 //EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00628 //<< " Sending app packet " << appData->getName() << " over IPv6" 00629 //<< endl; 00630 IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo(); 00631 ipControlInfo->setProtocol(IP_PROT_UDP); 00632 ipControlInfo->setSrcAddr(srcAddr.get6()); 00633 ipControlInfo->setDestAddr(destAddr.get6()); 00634 // ipControlInfo->setInterfaceId(udpCtrl->InterfaceId()); FIXME extend IPv6 with this!!! 00635 udpPacket->setControlInfo(ipControlInfo); 00636 delete udpCtrl; 00637 } 00638 00639 SimpleInfo* info = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(destAddr)); 00640 numSent++; 00641 00642 if (info == NULL) { 00643 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00644 << " No route to host " << destAddr 00645 << endl; 00646 00647 delete udpPacket; 00648 numDestUnavailableLost++; 00649 return; 00650 } 00651 00652 SimpleNodeEntry* destEntry = info->getEntry(); 00653 00654 // calculate delay 00655 simtime_t totalDelay = 0; 00656 if (srcAddr != destAddr) { 00657 SimpleNodeEntry::SimpleDelay temp; 00658 if (faultyDelay) { 00659 SimpleInfo* thisInfo = static_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr)); 00660 temp = nodeEntry->calcDelay(udpPacket, *destEntry, 00661 !(thisInfo->getNpsLayer() == 0 || 00662 info->getNpsLayer() == 0)); //TODO 00663 } else { 00664 temp = nodeEntry->calcDelay(udpPacket, *destEntry); 00665 } 00666 if (useCoordinateBasedDelay == false) { 00667 totalDelay = constantDelay; 00668 } else if (temp.second == false) { 00669 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00670 << " Send queue full: packet " << udpPacket << " dropped" 00671 << endl; 00672 delete udpPacket; 00673 numQueueLost++; 00674 return; 00675 } else { 00676 totalDelay = temp.first; 00677 } 00678 } 00679 00680 SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(globalNodeList->getPeerInfo(srcAddr)); 00681 00682 if (!globalNodeList->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) { 00683 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00684 << " Partition " << thisInfo->getTypeID() << "->" << info->getTypeID() 00685 << " is not connected" 00686 << endl; 00687 delete udpPacket; 00688 numPartitionLost++; 00689 return; 00690 } 00691 00692 if (jitter) { 00693 // jitter 00694 //totalDelay += truncnormal(0, SIMTIME_DBL(totalDelay) * jitter); 00695 00696 //workaround (bug in truncnormal(): sometimes returns inf) 00697 double temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter); 00698 while (temp == INFINITY || temp != temp) { // reroll if temp is INF or NaN 00699 std::cerr << "\n******* SimpleUDP: truncnormal() -> inf !!\n" 00700 << std::endl; 00701 temp = truncnormal(0, SIMTIME_DBL(totalDelay) * jitter); 00702 } 00703 00704 totalDelay += temp; 00705 } 00706 00707 if (udpPacket != NULL) { 00708 BaseOverlayMessage* temp = NULL; 00709 00710 if (ev.isGUI() && udpPacket->getEncapsulatedPacket()) { 00711 if ((temp = dynamic_cast<BaseOverlayMessage*>(udpPacket 00712 ->getEncapsulatedPacket()))) { 00713 switch (temp->getStatType()) { 00714 case APP_DATA_STAT: 00715 udpPacket->setKind(1); 00716 break; 00717 case APP_LOOKUP_STAT: 00718 udpPacket->setKind(2); 00719 break; 00720 case MAINTENANCE_STAT: 00721 default: 00722 udpPacket->setKind(3); 00723 } 00724 } else { 00725 udpPacket->setKind(1); 00726 } 00727 } 00728 00729 EV << "[SimpleUDP::processMsgFromApp() @ " << IPAddressResolver().addressOf(node) << "]\n" 00730 << " Packet " << udpPacket << " sent with delay = " << totalDelay 00731 << endl; 00732 00733 //RECORD_STATS(globalStatistics->addStdDev("SimpleUDP: delay", totalDelay)); 00734 00735 sendDirect(udpPacket, totalDelay, 0, destEntry->getGate()); 00736 } 00737 }
void SimpleUDP::processUDPPacket | ( | SimpleUDPPacket * | udpPacket | ) | [protected, virtual] |
process UDP packets coming from IP
udpPacket | the received packet |
Definition at line 501 of file SimpleUDP.cc.
Referenced by handleMessage().
00502 { 00503 cModule *node = getParentModule(); 00504 // IPvXAddress ip = IPAddressResolver().addressOf(node); 00505 // Speedhack SK 00506 00507 // simulate checksum: discard packet if it has bit error 00508 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00509 << " Packet " << udpPacket->getName() << " received from network, dest port " << udpPacket->getDestinationPort() 00510 << endl; 00511 00512 if (udpPacket->hasBitError()) { 00513 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00514 << " Packet has bit error, discarding" 00515 << endl; 00516 delete udpPacket; 00517 numDroppedBadChecksum++; 00518 return; 00519 } 00520 00521 int destPort = udpPacket->getDestinationPort(); 00522 cPolymorphic *ctrl = udpPacket->removeControlInfo(); 00523 00524 // send back ICMP error if no socket is bound to that port 00525 SocketsByPortMap::iterator it = socketsByPortMap.find(destPort); 00526 if (it==socketsByPortMap.end()) { 00527 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00528 << " No socket registered on port " << destPort 00529 << endl; 00530 processUndeliverablePacket(udpPacket, ctrl); 00531 return; 00532 } 00533 SockDescList& list = it->second; 00534 00535 int matches = 0; 00536 00537 // deliver a copy of the packet to each matching socket 00538 // cMessage *payload = udpPacket->getEncapsulatedPacket(); 00539 cMessage *payload = udpPacket->decapsulate(); 00540 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { 00541 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; 00542 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00543 SockDesc *sd = *it; 00544 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl4)) { 00545 // EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00546 // << " Socket sockId=" << sd->sockId << " matches, sending up a copy" 00547 // << endl; 00548 // sendUp((cMessage*)payload->dup(), udpPacket, ctrl4, sd); 00549 // ib: speed hack 00550 00551 if (matches == 0) { 00552 sendUp(payload, udpPacket, ctrl4, sd); 00553 } else 00554 opp_error("Edit SimpleUDP.cc to support multibinding."); 00555 matches++; 00556 } 00557 } 00558 } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->getControlInfo()) 00559 !=NULL) { 00560 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; 00561 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) { 00562 SockDesc *sd = *it; 00563 if (sd->onlyLocalPortIsSet || matchesSocket(sd, udpPacket, ctrl6)) { 00564 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00565 << " Socket sockId=" << sd->sockId << " matches, sending up a copy" 00566 << endl; 00567 sendUp((cMessage*)payload->dup(), udpPacket, ctrl6, sd); 00568 matches++; 00569 } 00570 } 00571 } else { 00572 error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName()); 00573 } 00574 00575 // send back ICMP error if there is no matching socket 00576 if (matches==0) { 00577 EV << "[SimpleUDP::processUDPPacket() @ " << IPAddressResolver().addressOf(node) << "]\n" 00578 << " None of the sockets on port " << destPort << " matches the packet" 00579 << endl; 00580 processUndeliverablePacket(udpPacket, ctrl) 00581 ; 00582 return; 00583 } 00584 00585 delete udpPacket; 00586 delete ctrl; 00587 }
void SimpleUDP::processUndeliverablePacket | ( | SimpleUDPPacket * | udpPacket, | |
cPolymorphic * | ctrl | |||
) | [protected] |
handles received packet which destination port is not bound to any socket
udpPacket | the SimpleUDPPacket with the wrong port number | |
ctrl | the IPControlInfo of udpPacket |
Definition at line 382 of file SimpleUDP.cc.
Referenced by processUDPPacket().
00383 { 00384 numDroppedWrongPort++; 00385 00386 // send back ICMP PORT_UNREACHABLE 00387 if (dynamic_cast<IPControlInfo *>(ctrl)!=NULL) { 00388 /* if (!icmp) 00389 icmp = ICMPAccess().get(); 00390 IPControlInfo *ctrl4 = (IPControlInfo *)ctrl; 00391 if (!ctrl4->getDestAddr().isMulticast()) 00392 icmp->sendErrorMessage(udpPacket, ctrl4, ICMP_DESTINATION_UNREACHABLE, ICMP_DU_PORT_UNREACHABLE);*/ 00393 /* TODO: implement icmp module */ 00394 EV << "[SimpleUDP::processUndeliverablePacket()]\n" 00395 << " Dropped packet bound to unreserved port, ignoring ICMP error" 00396 << endl; 00397 } else if (dynamic_cast<IPv6ControlInfo *>(udpPacket->getControlInfo()) 00398 !=NULL) { 00399 /* if (!icmpv6) 00400 icmpv6 = ICMPv6Access().get(); 00401 IPv6ControlInfo *ctrl6 = (IPv6ControlInfo *)ctrl; 00402 if (!ctrl6->getDestAddr().isMulticast()) 00403 icmpv6->sendErrorMessage(udpPacket, ctrl6, ICMPv6_DESTINATION_UNREACHABLE, PORT_UNREACHABLE);*/ 00404 /* TODO: implement icmp module */ 00405 EV << "[SimpleUDP::processUndeliverablePacket()]\n" 00406 << " Dropped packet bound to unreserved port, ignoring ICMP error" 00407 << endl; 00408 } else { 00409 error("(%s)%s arrived from lower layer without control info", udpPacket->getClassName(), udpPacket->getName()); 00410 } 00411 }
void SimpleUDP::sendUp | ( | cMessage * | payload, | |
SimpleUDPPacket * | udpHeader, | |||
IPv6ControlInfo * | ctrl, | |||
SockDesc * | sd | |||
) | [protected] |
sends payload up to the application
payload | the payload | |
udpHeader | the udpHeader of the IPv6 message | |
ctrl | the IPControlInfo of the IPv6 message | |
sd | the socket at which the IPv6 message arrived |
Definition at line 365 of file SimpleUDP.cc.
00366 { 00367 // send payload with UDPControlInfo up to the application -- IPv6 version 00368 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00369 udpCtrl->setSockId(sd->sockId); 00370 udpCtrl->setUserId(sd->userId); 00371 udpCtrl->setSrcAddr(ipCtrl->getSrcAddr()); 00372 udpCtrl->setDestAddr(ipCtrl->getDestAddr()); 00373 udpCtrl->setSrcPort(udpHeader->getSourcePort()); 00374 udpCtrl->setDestPort(udpHeader->getDestinationPort()); 00375 udpCtrl->setInterfaceId(ipCtrl->getInterfaceId()); 00376 payload->setControlInfo(udpCtrl); 00377 00378 send(payload, "appOut", sd->appGateIndex); 00379 numPassedUp++; 00380 }
void SimpleUDP::sendUp | ( | cMessage * | payload, | |
SimpleUDPPacket * | udpHeader, | |||
IPControlInfo * | ctrl, | |||
SockDesc * | sd | |||
) | [protected] |
sends payload up to the application
payload | the payload | |
udpHeader | the udpHeader of the IPv4 message | |
ctrl | the IPControlInfo of the IPv4 message | |
sd | the socket at which the IPv4 message arrived |
Definition at line 348 of file SimpleUDP.cc.
Referenced by processUDPPacket().
00349 { 00350 // send payload with UDPControlInfo up to the application -- IPv4 version 00351 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00352 udpCtrl->setSockId(sd->sockId); 00353 udpCtrl->setUserId(sd->userId); 00354 udpCtrl->setSrcAddr(ipCtrl->getSrcAddr()); 00355 udpCtrl->setDestAddr(ipCtrl->getDestAddr()); 00356 udpCtrl->setSrcPort(udpHeader->getSourcePort()); 00357 udpCtrl->setDestPort(udpHeader->getDestinationPort()); 00358 udpCtrl->setInterfaceId(ipCtrl->getInterfaceId()); 00359 payload->setControlInfo(udpCtrl); 00360 00361 send(payload, "appOut", sd->appGateIndex); 00362 numPassedUp++; 00363 }
void SimpleUDP::sendUpErrorNotification | ( | SockDesc * | sd, | |
int | msgkind, | |||
const IPvXAddress & | localAddr, | |||
const IPvXAddress & | remoteAddr, | |||
short | remotePort | |||
) | [protected] |
sends an error up to the application
sd | the socket that received the error | |
msgkind | the type of the error notification | |
localAddr | the address from which the faulty message was sent | |
remoteAddr | the address to which the faulty message was sent | |
remotePort | the port to which the faulty message was sent |
Definition at line 486 of file SimpleUDP.cc.
Referenced by processICMPError().
00487 { 00488 cMessage *notifyMsg = new cMessage("ERROR", msgkind); 00489 UDPControlInfo *udpCtrl = new UDPControlInfo(); 00490 udpCtrl->setSockId(sd->sockId); 00491 udpCtrl->setUserId(sd->userId); 00492 udpCtrl->setSrcAddr(localAddr); 00493 udpCtrl->setDestAddr(remoteAddr); 00494 udpCtrl->setSrcPort(sd->localPort); 00495 udpCtrl->setDestPort(remotePort); 00496 notifyMsg->setControlInfo(udpCtrl); 00497 00498 send(notifyMsg, "appOut", sd->appGateIndex); 00499 }
void SimpleUDP::setNodeEntry | ( | SimpleNodeEntry * | entry | ) |
set or change the nodeEntry of this module
entry | the new nodeEntry |
Definition at line 761 of file SimpleUDP.cc.
Referenced by SimpleUnderlayConfigurator::createNode(), and SimpleUnderlayConfigurator::migrateNode().
00762 { 00763 nodeEntry = entry; 00764 }
void SimpleUDP::unbind | ( | int | sockId | ) | [protected] |
unbind socket
sockId | id of the socket to unbind |
Definition at line 234 of file SimpleUDP.cc.
Referenced by processCommandFromApp().
00235 { 00236 // remove from socketsByIdMap 00237 SocketsByIdMap::iterator it = socketsByIdMap.find(sockId); 00238 if (it==socketsByIdMap.end()) 00239 error("socket id=%d doesn't exist (already closed?)", sockId); 00240 SockDesc *sd = it->second; 00241 socketsByIdMap.erase(it); 00242 00243 EV << "[SimpleUDP::unbind() @ " << sd->localAddr << "]\n" 00244 << " Unbinding socket: " << *sd 00245 << endl; 00246 00247 // remove from socketsByPortMap 00248 SockDescList& list = socketsByPortMap[sd->localPort]; 00249 for (SockDescList::iterator it=list.begin(); it!=list.end(); ++it) 00250 if (*it == sd) { 00251 list.erase(it); 00252 break; 00253 } 00254 if (list.empty()) 00255 socketsByPortMap.erase(sd->localPort); 00256 delete sd; 00257 }
void SimpleUDP::updateDisplayString | ( | ) | [protected] |
utility: show current statistics above the icon
Definition at line 298 of file SimpleUDP.cc.
Referenced by handleMessage().
00299 { 00300 char buf[80]; 00301 sprintf(buf, "passed up: %d pks\nsent: %d pks", numPassedUp, numSent); 00302 if (numDroppedWrongPort>0) { 00303 sprintf(buf+strlen(buf), "\ndropped (no app): %d pks", numDroppedWrongPort); 00304 getDisplayString().setTagArg("i",1,"red"); 00305 } 00306 if (numQueueLost>0) { 00307 sprintf(buf+strlen(buf), "\nlost (queue overflow): %d pks", numQueueLost); 00308 getDisplayString().setTagArg("i",1,"red"); 00309 } 00310 getDisplayString().setTagArg("t",0,buf); 00311 }
simtime_t SimpleUDP::constantDelay [protected] |
constant delay between two peers
Definition at line 118 of file SimpleUDP.h.
Referenced by initialize(), and processMsgFromApp().
simtime_t SimpleUDP::delay [protected] |
simulated delay between sending and receiving udp module
Definition at line 116 of file SimpleUDP.h.
std::map< std::string, SimpleUDP::delayFaultTypeNum > SimpleUDP::delayFaultTypeMap [static] |
Definition at line 96 of file SimpleUDP.h.
Referenced by SimpleNodeEntry::getFaultyDelay(), and initialize().
std::string SimpleUDP::delayFaultTypeString [static] |
Definition at line 89 of file SimpleUDP.h.
Referenced by SimpleNodeEntry::getFaultyDelay(), and initialize().
bool SimpleUDP::faultyDelay [protected] |
Definition at line 121 of file SimpleUDP.h.
Referenced by initialize(), and processMsgFromApp().
GlobalNodeList* SimpleUDP::globalNodeList [protected] |
violate the triangle inequality?
pointer to GlobalNodeList
Definition at line 122 of file SimpleUDP.h.
Referenced by initialize(), and processMsgFromApp().
GlobalStatistics* SimpleUDP::globalStatistics [protected] |
pointer to GlobalStatistics
Definition at line 123 of file SimpleUDP.h.
Referenced by finish(), initialize(), and SimpleUDP().
ICMP* SimpleUDP::icmp [protected] |
pointer to a received icmp (IPv4) message
Definition at line 105 of file SimpleUDP.h.
Referenced by initialize().
ICMPv6* SimpleUDP::icmpv6 [protected] |
pointer to a received icmp (IPv6) message
Definition at line 106 of file SimpleUDP.h.
Referenced by initialize().
double SimpleUDP::jitter [protected] |
amount of jitter in % of total delay
Definition at line 120 of file SimpleUDP.h.
Referenced by initialize(), and processMsgFromApp().
short SimpleUDP::lastEphemeralPort [protected] |
last used port (all ports above should be free)
Definition at line 104 of file SimpleUDP.h.
Referenced by getEphemeralPort(), and initialize().
SimpleNodeEntry* SimpleUDP::nodeEntry [protected] |
nodeEntry of the overlay node this module belongs to
Definition at line 124 of file SimpleUDP.h.
Referenced by initialize(), processMsgFromApp(), and setNodeEntry().
int SimpleUDP::numDestUnavailableLost [protected] |
number of lost packets due to unavailable destination
Definition at line 115 of file SimpleUDP.h.
Referenced by finish(), initialize(), and processMsgFromApp().
int SimpleUDP::numDroppedBadChecksum [protected] |
number of dropped packets due to bad checksum
Definition at line 112 of file SimpleUDP.h.
Referenced by finish(), initialize(), and processUDPPacket().
int SimpleUDP::numDroppedWrongPort [protected] |
number of dropped packets due to wrong destination port
Definition at line 111 of file SimpleUDP.h.
Referenced by initialize(), processUndeliverablePacket(), and updateDisplayString().
int SimpleUDP::numPartitionLost [protected] |
number of lost packets due to network partitions
Definition at line 114 of file SimpleUDP.h.
Referenced by finish(), initialize(), and processMsgFromApp().
int SimpleUDP::numPassedUp [protected] |
number of packet passed up to applications
Definition at line 110 of file SimpleUDP.h.
Referenced by initialize(), sendUp(), and updateDisplayString().
int SimpleUDP::numQueueLost [protected] |
number of lost packets due to queue full
Definition at line 113 of file SimpleUDP.h.
Referenced by finish(), initialize(), processMsgFromApp(), and updateDisplayString().
int SimpleUDP::numSent [protected] |
number of packets sent to the network
Definition at line 109 of file SimpleUDP.h.
Referenced by finish(), initialize(), processMsgFromApp(), and updateDisplayString().
SocketsByIdMap SimpleUDP::socketsByIdMap [protected] |
list of socket ordered by sockId
Definition at line 100 of file SimpleUDP.h.
Referenced by bind(), connect(), initialize(), unbind(), and ~SimpleUDP().
SocketsByPortMap SimpleUDP::socketsByPortMap [protected] |
list of sockets ordered by localPort
Definition at line 101 of file SimpleUDP.h.
Referenced by bind(), getEphemeralPort(), initialize(), processICMPError(), processUDPPacket(), and unbind().
bool SimpleUDP::useCoordinateBasedDelay [protected] |
delay should be calculated from euklidean distance between two peers
Definition at line 119 of file SimpleUDP.h.
Referenced by initialize(), and processMsgFromApp().