void tracker_addOutputBytes(Tracker* tracker, Packet* packet, gint handle) { MAGIC_ASSERT(tracker); TrackerFlags flags = _tracker_getFlags(tracker); if(!(flags & TRACKER_FLAGS_NODE) && !(flags & TRACKER_FLAGS_SOCKET)) { return; } gboolean isLocal = packet_getSourceIP(packet) == htonl(INADDR_LOOPBACK); gsize header = (gsize)packet_getHeaderSize(packet); gsize payload = (gsize)packet_getPayloadLength(packet); PacketDeliveryStatusFlags status = packet_getDeliveryStatus(packet); if(flags & TRACKER_FLAGS_NODE) { if(isLocal) { _tracker_updateCounters(&tracker->local.outCounters, header, payload, status); } else { _tracker_updateCounters(&tracker->remote.outCounters, header, payload, status); } } if(flags & TRACKER_FLAGS_SOCKET) { SocketStats* ss = g_hash_table_lookup(tracker->socketStats, &handle); if(ss) { if(isLocal) { _tracker_updateCounters(&ss->local.outCounters, header, payload, status); } else { _tracker_updateCounters(&ss->remote.outCounters, header, payload, status); } } } }
gboolean socket_addToOutputBuffer(Socket* socket, Packet* packet) { MAGIC_ASSERT(socket); /* check if the packet fits */ guint length = packet_getPayloadLength(packet); if(length > socket_getOutputBufferSpace(socket)) { return FALSE; } /* add to our queue */ g_queue_push_tail(socket->outputBuffer, packet); socket->outputBufferLength += length; packet_addDeliveryStatus(packet, PDS_SND_SOCKET_BUFFERED); /* update the tracker input buffer stats */ Tracker* tracker = host_getTracker(worker_getCurrentHost()); Descriptor* descriptor = (Descriptor *)socket; tracker_updateSocketOutputBuffer(tracker, descriptor->handle, socket->outputBufferLength, socket->outputBufferSize); /* we just added a packet, we are no longer writable if full */ if(socket_getOutputBufferSpace(socket) <= 0) { descriptor_adjustStatus((Descriptor*)socket, DS_WRITABLE, FALSE); } /* tell the interface to include us when sending out to the network */ in_addr_t ip = packet_getSourceIP(packet); NetworkInterface* interface = host_lookupInterface(worker_getCurrentHost(), ip); networkinterface_wantsSend(interface, socket); return TRUE; }
static void _networkinterface_dropInboundPacket(NetworkInterface* interface, Packet* packet) { MAGIC_ASSERT(interface); /* drop incoming packet that traversed the network link from source */ if(networkinterface_getIPAddress(interface) == packet_getSourceIP(packet)) { /* packet is on our own interface, so event destination is our node */ PacketDroppedEvent* event = packetdropped_new(packet); worker_scheduleEvent((Event*)event, 1, 0); } else { /* let the network schedule the event with appropriate delays */ network_scheduleRetransmit(interface->network, packet); } }
void networkinterface_packetDropped(NetworkInterface* interface, Packet* packet) { MAGIC_ASSERT(interface); /* * someone dropped a packet belonging to our interface * hand it off to the correct socket layer */ gint key = packet_getSourceAssociationKey(packet); Socket* socket = g_hash_table_lookup(interface->boundSockets, GINT_TO_POINTER(key)); /* just ignore if the socket closed in the meantime */ if(socket) { socket_droppedPacket(socket, packet); } else { in_addr_t ip = packet_getSourceIP(packet); gchar* ipString = address_ipToNewString(ip); debug("interface dropping packet from %s:%u, no socket registered at %i", ipString, packet_getSourcePort(packet), key); g_free(ipString); } }
void worker_schedulePacket(Packet* packet) { /* get our thread-private worker */ Worker* worker = _worker_getPrivate(); if(slave_isKilled(worker->slave)) { /* the simulation is over, don't bother */ return; } in_addr_t srcIP = packet_getSourceIP(packet); in_addr_t dstIP = packet_getDestinationIP(packet); Address* srcAddress = dns_resolveIPToAddress(worker_getDNS(), (guint32) srcIP); Address* dstAddress = dns_resolveIPToAddress(worker_getDNS(), (guint32) dstIP); if(!srcAddress || !dstAddress) { error("unable to schedule packet because of null addresses"); return; } /* check if network reliability forces us to 'drop' the packet */ gdouble reliability = topology_getReliability(worker_getTopology(), srcAddress, dstAddress); Random* random = host_getRandom(worker_getCurrentHost()); gdouble chance = random_nextDouble(random); /* don't drop control packets with length 0, otherwise congestion * control has problems responding to packet loss */ if(chance <= reliability || packet_getPayloadLength(packet) == 0) { /* the sender's packet will make it through, find latency */ gdouble latency = topology_getLatency(worker_getTopology(), srcAddress, dstAddress); SimulationTime delay = (SimulationTime) ceil(latency * SIMTIME_ONE_MILLISECOND); PacketArrivedEvent* event = packetarrived_new(packet); worker_scheduleEvent((Event*)event, delay, (GQuark)address_getID(dstAddress)); packet_addDeliveryStatus(packet, PDS_INET_SENT); } else { packet_addDeliveryStatus(packet, PDS_INET_DROPPED); } }
gssize udp_receiveUserData(UDP* udp, gpointer buffer, gsize nBytes, in_addr_t* ip, in_port_t* port) { MAGIC_ASSERT(udp); Packet* packet = socket_removeFromInputBuffer((Socket*)udp); if(!packet) { return -1; } /* copy lesser of requested and available amount to application buffer */ guint packetLength = packet_getPayloadLength(packet); gsize copyLength = MIN(nBytes, packetLength); guint bytesCopied = packet_copyPayload(packet, 0, buffer, copyLength); utility_assert(bytesCopied == copyLength); packet_addDeliveryStatus(packet, PDS_RCV_SOCKET_DELIVERED); /* fill in address info */ if(ip) { *ip = packet_getSourceIP(packet); } if(port) { *port = packet_getSourcePort(packet); } /* destroy packet, throwing away any bytes not claimed by the app */ packet_unref(packet); /* update the tracker output buffer stats */ Tracker* tracker = host_getTracker(worker_getCurrentHost()); Socket* socket = (Socket* )udp; Descriptor* descriptor = (Descriptor *)socket; gsize outLength = socket_getOutputBufferLength(socket); gsize outSize = socket_getOutputBufferSize(socket); tracker_updateSocketOutputBuffer(tracker, descriptor->handle, outLength, outSize); debug("user read %u inbound UDP bytes", bytesCopied); return (gssize)bytesCopied; }